【问题标题】:d3 Wheel of Fortuned3 命运之轮
【发布时间】:2016-05-12 05:47:06
【问题描述】:

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

但现在我只是想创建一个平滑的拖动。

【问题讨论】:

    标签: javascript d3.js


    【解决方案1】:

    你的“紧张”的原因是你使用了相对于彼此的鼠标坐标。你要做的是使用一个固定点,即轮子的中心。

    因此,不要使用 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/

    【讨论】:

    • 感谢您的详细回复!这很有意义,而且效果很好。
    • 我还想问你是否知道有一种方法可以为触摸事件做同样的事情。 touchstart/end 事件是否有 X、Y?
    • @QuantumRich 看看这个例子bl.ocks.org/emeeks/9e6b87735d2da05813e3
    猜你喜欢
    • 2016-02-24
    • 2022-01-18
    • 2016-10-25
    • 1970-01-01
    • 2021-03-01
    • 2012-11-25
    • 1970-01-01
    • 2023-02-12
    • 1970-01-01
    相关资源
    最近更新 更多