你的“紧张”的原因是你使用了相对于彼此的鼠标坐标。你要做的是使用一个固定点,即轮子的中心。
因此,不要使用 d.event.x/y 更新 lastX 和 lastY ,只需将其保留为:
var lastX = width/2; //center points of circle
var lastY = height/2;
并像这样在你的算法中使用它:
if (isDown) {
var thisX = d3.event.x - lastX,
thisY = d3.event.y - lastY;
var angleDeg = Math.atan2(lastY - d3.event.y, lastX - d3.event.x) * 180 / Math.PI;
svg.attr("transform", "translate(" + width / 2 + "," + height / 2 + ") rotate(" + angleDeg + "," + 0 + "," + 0 + ")");
}
我已将它放在 JSFiddle 上,因为 plnkr 无法正常工作,鼠标事件等等:https://jsfiddle.net/thatOneGuy/ourpo8p7/1/
即使这样也不完美。
基本上这里发生的是,它获取鼠标坐标并旋转到该坐标。但是你不想要这个,你只希望它在你移动鼠标时移动,即使那样你也只希望它移动你移动光标的量,而不是跳转到光标(如果这甚至有意义的话:P)。
所以你要做的就是从0开始,如果你在鼠标按下时移动光标,保存旋转位置,所以当你重新开始时,你可以从你离开的地方开始。这很难解释。
无论如何,当鼠标按下时,保存鼠标坐标和圆心之间的角度:
var thisX = d3.event.x - lastX,
thisY = d3.event.y - lastY;
curAngle = Math.atan2(lastY - d3.event.y, lastX - d3.event.x)
if (curAngle < 0) curAngle += 2 * Math.PI; //make sure its positive
curAngle = curAngle * 180 / Math.PI; //change to degrees
现在在鼠标移动时,您必须将该值从计算的角度中移除,以便从 0 开始,但添加您旋转滚轮时计算的最后一个角度(如果有)。
var thisX = d3.event.x - lastX,
thisY = d3.event.y - lastY;
angleDeg = Math.atan2(lastY - d3.event.y, lastX - d3.event.x) // * 180 / Math.PI) - curAngle
if (angleDeg < 0) angleDeg += 2 * Math.PI;
angleDeg = angleDeg * 180 / Math.PI;
angleDeg = angleDeg - curAngle + finishAngle; //reset to 0 and add last rotation calculated
if (angleDeg < 0) angleDeg += 360;
d3.select('#degrees').text(Math.round(angleDeg))
svg.attr("transform", "translate(" + width / 2 + "," + height / 2 + ") rotate(" + angleDeg + "," + 0 + "," + 0 + ")");
最后,计算出上面mouseup时使用的旋转角度
finishAngle = angleDeg;
工作小提琴:https://jsfiddle.net/thatOneGuy/v8xce8k3/1/