旋转指向以弧度为单位的某物而不绕零
Rotating to point at something in radians without wrapping around zero
假设我有一个圆圈,上面有一条线。
我希望这条线指向 window 的中心,无论圆移动到哪里。
但是,我希望那条线慢慢移动到那个角度。我不想计算旋转并设置每一帧,而是计算并 tweened 到那个方向。
我遇到的问题是,如果您移动使直线围绕弧度与 0 的交点旋转,它将旋转 360(或 3.14 弧度;)以到达该点。
我花了一段时间想如何最好地解释这个问题,here is a codepen 希望可以帮助澄清我的问题
// CenterX/Y is the center of the screen.
// dotX/Y is the center of the circle.
var angleToCenter=Math.atan2(centerY-dotY,centerX-dotX);
if (angleToCenter<currentAngle) {
currentAngle-=0.05;
} else {
currentAngle+=0.05;
}
如果您移动到屏幕右侧,然后移动到中心上方或下方,您会看到该线移动一整圈以尝试到达计算的方向。我该如何避免这种情况?我希望直线通过最短的可能方式无缝旋转以指向中心,而不是 做一个完整的圆圈。
好问题。非常不一样。
我会为黑色圆圈下方 的任何位置定义反 (-1) 关系。这样,如果红色圆圈穿过水平轴 - 其边界由黑色圆圈定义 - 方程式的数学结果会反转。
这会变成我们通常认为的 0 度,现在定位为 180 度。
推理:看看你的CodePen,很明显词干是"the long way around",但你希望它是"short way around"。实现这一目标的最直观方法似乎是反转红色圆圈计算的旋转。我能想到的最简单的方法就是反转圆的极性。
问题在于 angleToCenter
从 Math.PI
切换到 -Math.PI
(反之亦然)。
因此,我建议您创建一个 "epsilon angle distance",其中角度将被硬编码:
var angleToCenter = Math.atan2(centerY - dotY, centerX - dotX);
var epsilon = 0.05;
if (Math.abs(angleToCenter - Math.PI) <= epsilon / 2 || Math.abs(angleToCenter + Math.PI) <= epsilon / 2) {
if (dotY > centerY) {
currentAngle = -Math.PI;
} else if (dotY < centerY) {
currentAngle = Math.PI;
}
} else if (angleToCenter < currentAngle - epsilon) {
currentAngle -= epsilon;
} else {
currentAngle += epsilon;
}
对于完整的编辑,您可以查看my fork to your CodePan
假设我有一个圆圈,上面有一条线。
我希望这条线指向 window 的中心,无论圆移动到哪里。
但是,我希望那条线慢慢移动到那个角度。我不想计算旋转并设置每一帧,而是计算并 tweened 到那个方向。
我遇到的问题是,如果您移动使直线围绕弧度与 0 的交点旋转,它将旋转 360(或 3.14 弧度;)以到达该点。
我花了一段时间想如何最好地解释这个问题,here is a codepen 希望可以帮助澄清我的问题
// CenterX/Y is the center of the screen.
// dotX/Y is the center of the circle.
var angleToCenter=Math.atan2(centerY-dotY,centerX-dotX);
if (angleToCenter<currentAngle) {
currentAngle-=0.05;
} else {
currentAngle+=0.05;
}
如果您移动到屏幕右侧,然后移动到中心上方或下方,您会看到该线移动一整圈以尝试到达计算的方向。我该如何避免这种情况?我希望直线通过最短的可能方式无缝旋转以指向中心,而不是 做一个完整的圆圈。
好问题。非常不一样。
我会为黑色圆圈下方 的任何位置定义反 (-1) 关系。这样,如果红色圆圈穿过水平轴 - 其边界由黑色圆圈定义 - 方程式的数学结果会反转。
这会变成我们通常认为的 0 度,现在定位为 180 度。
推理:看看你的CodePen,很明显词干是"the long way around",但你希望它是"short way around"。实现这一目标的最直观方法似乎是反转红色圆圈计算的旋转。我能想到的最简单的方法就是反转圆的极性。
问题在于 angleToCenter
从 Math.PI
切换到 -Math.PI
(反之亦然)。
因此,我建议您创建一个 "epsilon angle distance",其中角度将被硬编码:
var angleToCenter = Math.atan2(centerY - dotY, centerX - dotX);
var epsilon = 0.05;
if (Math.abs(angleToCenter - Math.PI) <= epsilon / 2 || Math.abs(angleToCenter + Math.PI) <= epsilon / 2) {
if (dotY > centerY) {
currentAngle = -Math.PI;
} else if (dotY < centerY) {
currentAngle = Math.PI;
}
} else if (angleToCenter < currentAngle - epsilon) {
currentAngle -= epsilon;
} else {
currentAngle += epsilon;
}
对于完整的编辑,您可以查看my fork to your CodePan