javascript - d3 命运之轮

标签 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 在鼠标移动期间获取圆上两点之间的 Angular ,并相应地更改饼图 Angular 。似乎我拥有的差不多了,但是有滞后/抖动。我可以做些什么来平滑它,使其看起来像这样吗? : http://www.fusioncharts.com/charts/pie2d_5/

理想情况下,从长远来看,我希望 mouseup 事件为旋转创建某种速度,并且能够查询指向上方的任何切片。

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

最佳答案

你之所以“紧张”是因为你使用的鼠标坐标是相互关联的。你想要做的是使用一个固定点,即车轮的中心。

因此,不要使用 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 开始,如果你在鼠标按下时移动光标,保存旋转的位置,这样当你再次开始时你可以从你离开的地方开始。这很难解释。

无论如何,当鼠标按下时,保存鼠标坐标和圆心之间的 Angular :

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

现在在鼠标移动时,您必须将此值从计算的 Angular 中减去,因此您从 0 开始,但添加旋转滚轮时计算的最后一个 Angular (如果有)。

 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

时要使用的旋转 Angular
 finishAngle = angleDeg;

工作 fiddle :https://jsfiddle.net/thatOneGuy/v8xce8k3/1/

关于javascript - d3 命运之轮,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37178251/

相关文章:

javascript - jQuery 年份选择器

javascript - 如何在 IE9 剥离之前获取样式属性值

javascript - 如何通过添加总计和排序进行自动类型推断

javascript - d3 reduce 方法返回 NaN

javascript - d3js : Uncaught TypeError: Cannot read property 'length' of undefined

d3.js - DC.js 折线图 - 没有显示折线

javascript - 批量加载时向 THREE.Mesh() 添加名称时出现问题

javascript - Meteor-Up 部署失败

javascript - 无法使标签在可缩放的 d3 sunburst 上工作

javascript - 如何更改日历在文本框上的可见性单击