To get straight to the point, what I hope to achieve is to be able to create a connecting line between two elements with this shape:
When the elements move, the line resets but always maintains a 90 degree angle, instead of being a straight or diagonal line between [x,y] to [x,y].
Is there some kind of algorithm for this? Maybe a grid with some kind of A* implementation?
I don't know how to make rounded corners easy, but the easiest example will be this:
const canvas = document.querySelector('canvas')
const ctx = canvas.getContext('2d')
// define the points
const p1 = {
x: 30,
y: 50
}
const p2 = {
x: 150,
y: 130
}
ctx.strokeStyle = 'red'
// draw the points
ctx.beginPath()
ctx.arc(p1.x, p1.y, 5, 0, Math.PI * 2)
ctx.stroke()
ctx.beginPath()
ctx.arc(p2.x, p2.y, 5, 0, Math.PI * 2)
ctx.stroke()
// get distance between
const horizontalDistance = p2.x - p1.x
ctx.strokeStyle = 'black'
// draw left part
ctx.beginPath()
ctx.moveTo(p1.x, p1.y)
ctx.lineTo(p1.x + horizontalDistance / 2, p1.y)
ctx.stroke()
// draw vertical part
ctx.beginPath()
ctx.moveTo(p1.x + horizontalDistance / 2, p1.y)
ctx.lineTo(p1.x + horizontalDistance / 2, p2.y)
ctx.stroke()
// draw right part
ctx.beginPath()
ctx.moveTo(p1.x + horizontalDistance / 2, p2.y)
ctx.lineTo(p2.x, p2.y)
ctx.stroke()
canvas {
border: 1px solid black;
}
<canvas></canvas>
Real-time version:
const canvas = document.querySelector('canvas')
const ctx = canvas.getContext('2d')
const p1 = {
x: canvas.width / 2,
y: canvas.height / 2
}
const p2 = {
x: 150,
y: 130
}
canvas.addEventListener('mousemove', e => {
const mousePos = getMousePos(canvas, e)
p2.x = mousePos.x
p2.y = mousePos.y
})
loop()
function loop() {
draw()
requestAnimationFrame(loop)
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height)
ctx.strokeStyle = 'red'
ctx.beginPath()
ctx.arc(p1.x, p1.y, 5, 0, Math.PI * 2)
ctx.stroke()
ctx.beginPath()
ctx.arc(p2.x, p2.y, 5, 0, Math.PI * 2)
ctx.stroke()
const horizontalDistance = p2.x - p1.x
ctx.strokeStyle = 'black'
ctx.beginPath()
ctx.moveTo(p1.x, p1.y)
ctx.lineTo(p1.x + horizontalDistance / 2, p1.y)
ctx.stroke()
ctx.beginPath()
ctx.moveTo(p1.x + horizontalDistance / 2, p1.y)
ctx.lineTo(p1.x + horizontalDistance / 2, p2.y)
ctx.stroke()
ctx.beginPath()
ctx.moveTo(p1.x + horizontalDistance / 2, p2.y)
ctx.lineTo(p2.x, p2.y)
ctx.stroke()
}
function getMousePos(canvas, evt) {
const rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
canvas {
border: 1px solid black;
}
<canvas></canvas>
const canvas = document.querySelector('canvas')
const ctx = canvas.getContext('2d')
// define the points
const p1 = {
x: 30,
y: 50
}
const p2 = {
x: 150,
y: 130
}
ctx.strokeStyle = 'red'
// draw the points
ctx.beginPath()
ctx.arc(p1.x, p1.y, 5, 0, Math.PI * 2)
ctx.stroke()
ctx.beginPath()
ctx.arc(p2.x, p2.y, 5, 0, Math.PI * 2)
ctx.stroke()
// get distance between
const horizontalDistance = p2.x - p1.x
const verticalDistance = p2.y - p1.y
ctx.strokeStyle = 'black'
// draw left part
ctx.beginPath()
ctx.moveTo(p1.x, p1.y)
ctx.quadraticCurveTo(
p1.x + horizontalDistance / 2, p1.y,
p1.x + horizontalDistance / 2, p1.y + verticalDistance / 2
)
ctx.stroke()
// draw right part
ctx.beginPath()
ctx.moveTo(p1.x + horizontalDistance / 2, p1.y + verticalDistance / 2)
ctx.quadraticCurveTo(
p1.x + horizontalDistance / 2, p2.y,
p2.x, p2.y
)
ctx.lineTo(p2.x, p2.y)
ctx.stroke()
canvas {
border: 1px solid black;
}
<canvas></canvas>
It's possible to use quadratic curves to make the lines more curvy
const canvas = document.querySelector('canvas')
const ctx = canvas.getContext('2d')
const p1 = {
x: canvas.width / 2,
y: canvas.height / 2
}
const p2 = {
x: 150,
y: 130
}
canvas.addEventListener('mousemove', e => {
const mousePos = getMousePos(canvas, e)
p2.x = mousePos.x
p2.y = mousePos.y
})
loop()
function loop() {
draw()
requestAnimationFrame(loop)
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height)
ctx.strokeStyle = 'red'
ctx.beginPath()
ctx.arc(p1.x, p1.y, 5, 0, Math.PI * 2)
ctx.stroke()
ctx.beginPath()
ctx.arc(p2.x, p2.y, 5, 0, Math.PI * 2)
ctx.stroke()
const horizontalDistance = p2.x - p1.x
ctx.strokeStyle = 'black'
ctx.beginPath()
ctx.moveTo(p1.x, p1.y)
ctx.lineTo(p1.x + horizontalDistance / 2, p1.y)
ctx.stroke()
ctx.beginPath()
ctx.moveTo(p1.x + horizontalDistance / 2, p1.y)
ctx.lineTo(p1.x + horizontalDistance / 2, p2.y)
ctx.stroke()
ctx.beginPath()
ctx.moveTo(p1.x + horizontalDistance / 2, p2.y)
ctx.lineTo(p2.x, p2.y)
ctx.stroke()
}
function getMousePos(canvas, evt) {
const rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
canvas {
border: 1px solid black;
}
<canvas></canvas>