У вас есть одна точка на линии и угол, так что вы можете легко нарисовать линию, используя немного триго:
const pt1 = {
x: 120,
y: 100
};
const r = 30; // length of our segment, not really needed afterward
const ctx = canvas.getContext('2d');
function draw() {
const angle = inp.value;
// find pt2 using trigonometry
const pt2 = {
x: pt1.x + r * Math.cos(angle),
y: pt1.y + r * Math.sin(angle)
};
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillRect(pt1.x - 2, pt1.y - 2, 4, 4);
ctx.fillRect(pt2.x - 2, pt2.y - 2, 4, 4);
ctx.beginPath();
ctx.moveTo(pt1.x, pt1.y);
ctx.lineTo(pt2.x, pt2.y);
ctx.stroke();
}
inp.oninput = draw;
draw();
<input type="range" id="inp" min="0" max="6.29" step="0.01"><br>
<canvas id="canvas"></canvas>
Итак, теперь все, что вам нужно найти, это точка пересечения этих двух линий:
const line1 = {
x1: 30,
y1: 30,
x2: 10,
y2: 100
};
const pt1 = {
x: 80,
y: 80
}
const ctx = canvas.getContext('2d');
function draw(x, y) {
angle = inp.value;
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.strokeStyle = 'gray';
ctx.beginPath();
ctx.moveTo(line1.x1, line1.y1);
ctx.lineTo(line1.x2, line1.y2);
ctx.stroke();
const line2 = {
x1: pt1.x,
y1: pt1.y,
// here our radius can be hardcoded
x2: pt1.x + 1 * Math.cos(angle),
y2: pt1.y + 1 * Math.sin(angle)
}
const inter = intersect(
line1.x1, line1.y1, line1.x2, line1.y2,
line2.x1, line2.y1, line2.x2, line2.y2
);
if (!inter) {
ctx.fillText('parrallel', 20, 20);
return;
}
if (inter.x < Math.min(line1.x1, line1.x2) || inter.x > Math.max(line1.x1, line1.x2) ||
inter.y < Math.min(line1.y1, line1.y2) || inter.y > Math.max(line1.y1, line1.y2)) {
ctx.fillText('Out of bounds', 20, 20);
return;
}
ctx.strokeStyle = 'green';
ctx.beginPath();
ctx.moveTo(pt1.x, pt1.y);
ctx.lineTo(inter.x, inter.y);
ctx.stroke();
}
document.onmousemove = e => {
const rect = canvas.getBoundingClientRect();
pt1.x = e.clientX - rect.left;
pt1.y = e.clientY - rect.top;
draw();
};
inp.oninput = draw;
draw();
/* Edited from http://paulbourke.net/geometry/pointlineplane/javascript.txt */
function intersect(x1, y1, x2, y2, x3, y3, x4, y4) {
// Check if none of the lines are of length 0
if ((x1 === x2 && y1 === y2) || (x3 === x4 && y3 === y4)) {
return false
}
denominator = ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1))
// Lines are parallel
if (denominator === 0) {
return false
}
let ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denominator
let ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / denominator
// Return a object with the x and y coordinates of the intersection
let x = x1 + ua * (x2 - x1)
let y = y1 + ua * (y2 - y1)
return {
x,
y
}
}
<input type="range" id="inp" min="0" max="6.29" step="0.01" value="0"><br>
<canvas id="canvas"></canvas>
И вы заметите, что в этом случае нет точки " ближайший ", потому что у вас всегда будет не более одноготочка, которая будет соответствовать этим условиям.