Причина, по которой Math.atan
пропускает половину направлений, связана с знаком дроби. Круг имеет 4 квадранта, строки от {x: 0, y: 0}
до {x: 1, y: 1}
, {x: -1, y: 1}
, {x: -1, y: -1}
и {x: 1, y: -1}
дают только два значения (1 и -1), если вы разделите y
на x
например, 1/1 === 1
, 1/-1 === -1
, -1/1 === -1
и -1/-1 === 1
, таким образом, нет способа узнать, в каком из двух квадрантов присутствует каждое значение 1
и -1
.
Вы можете используйте Math.atan2
, чтобы получить угол от точки к другой точке в радианах. В диапазоне от -Math.PI
до Math.PI
(от -180 до 180 градусов)
Кстати, нет необходимости преобразовывать радианы в градусы, поскольку все математические функции в JavaScript используют радианы
requestAnimationFrame(mainLoop);
const ctx = canvas.getContext("2d")
canvas.height = canvas.width = 300;
canvas.style.backgroundColor = "#303030";
const mouse = {x: 0, y: 0};
canvas.addEventListener("mousemove", e => {
mouse.x = e.clientX;
mouse.y = e.clientY;
});
const shape = {
color: "lime",
x: 150,
y: 150,
size: 50,
path: [1, 0, -0.5, 0.7, -0.5, -0.7],
};
function draw(shape) {
var i = 0;
const s = shape.size, p = shape.path;
ctx.fillStyle = shape.color;
const rot = Math.atan2(mouse.y - shape.y, mouse.x - shape.x);
const xa = Math.cos(rot);
const ya = Math.sin(rot);
ctx.setTransform(xa, ya, -ya, xa, shape.x, shape.y);
ctx.beginPath();
while (i < p.length) { ctx.lineTo(p[i++] * s, p[i++] * s) }
ctx.fill();
}
function mainLoop() {
ctx.setTransform(1, 0, 0, 1, 0, 0); // set default transform
ctx.clearRect(0, 0, canvas.width, canvas.height);
draw(shape);
requestAnimationFrame(mainLoop);
}
body { margin: 0px; }
canvas { position: absolute; top: 0px; left: 0px; }
<canvas id="canvas"></canvas>