d3财富之轮

时间:2016-05-12 05:47:06

标签: javascript d3.js

我正在尝试使用可以在移动设备上运行的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事件为旋转创建某种速度,无论向上指向的切片都能够被查询。

但是现在我只想创造一个平滑的拖拽。

1 个答案:

答案 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;

工作小提琴:https://jsfiddle.net/thatOneGuy/v8xce8k3/1/