我正在尝试使用可以在移动设备上运行的d3.js创建一个交互式的财富轮。以下是我到目前为止所做的工作:http://plnkr.co/edit/JBJ1odoGvfWFODuIRqKZ
svg.on("mousemove", function(d) {
if (isDown){
var angleDeg = Math.atan2(lastY - d3.event.y, lastX - d3.event.x) * 180 / Math.PI;
lastX = d3.event.x;
lastY = d3.event.y;
curAngle = angleDeg;
svg.attr("transform", "translate(" + width / 2 + "," + height / 2 + ") rotate(" + curAngle + "," + 0 + "," + 0 + ")");
}
});
现在我正在尝试制作它,以便您可以单击并拖动饼图切片和"旋转"它只要鼠标停止就可以了。我正在使用Math.atan2来获取鼠标移动过程中圆上两点之间的角度,并相应地更改饼图角度。似乎我所拥有的几乎就在那里,但是存在滞后/抖动。我能做些什么来使这个变得平滑,这样看起来像这样吗? :http://www.fusioncharts.com/charts/pie2d_5/
理想情况下,从长远来看,我希望mouseup事件为旋转创建某种速度,无论向上指向的切片都能够被查询。
但是现在我只想创造一个平滑的拖拽。
答案 0 :(得分:4)
你的原因是“紧张不安”。是由于你使用相对于彼此的鼠标坐标。你想要做的是使用固定点,即车轮的中心。
因此,不要使用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;