Javascript d3命运之轮
我正在尝试使用d3.js创建一个可以在移动设备上工作的交互式命运之轮。以下是我到目前为止所做的工作: 现在,我正试图使它,以便您可以点击拖动饼图切片和“旋转”它周围,只要鼠标是下来。在鼠标移动期间,我使用Math.atan2获取圆上两点之间的角度,并相应地更改饼图角度。看起来我已经差不多做到了,但是有一个延迟/抖动。我能做些什么来平滑它,使它看起来像这样吗 理想情况下,从长远来看,我希望mouseup事件为旋转创建某种速度,并且无论指向上方的切片是什么,都能够被查询Javascript d3命运之轮,javascript,d3.js,Javascript,D3.js,我正在尝试使用d3.js创建一个可以在移动设备上工作的交互式命运之轮。以下是我到目前为止所做的工作: 现在,我正试图使它,以便您可以点击拖动饼图切片和“旋转”它周围,只要鼠标是下来。在鼠标移动期间,我使用Math.atan2获取圆上两点之间的角度,并相应地更改饼图角度。看起来我已经差不多做到了,但是有一个延迟/抖动。我能做些什么来平滑它,使它看起来像这样吗 理想情况下,从长远来看,我希望mouseup事件为旋转创建某种速度,并且无论指向上方的切片是什么,都能够被查询 但现在,我只是尝试创建一个平
但现在,我只是尝试创建一个平滑的拖动过程。您之所以会感到“不安”,是因为您使用了鼠标坐标。您要做的是使用一个固定点,即车轮的中心
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 + ")");
因此,与其使用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 + ")");
}
我把这个放在JSFIDLE上,因为plnkr不能正常工作,有鼠标事件等等:
即使这样也不完美
基本上,这里发生的是,获取鼠标坐标并旋转到该坐标。但是你不希望这样,你只希望它在你移动鼠标时移动,即使这样,你也只希望它按你移动光标的量移动,而不是跳转到光标(如果这有意义的话: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
工作小提琴:感谢您的详细回复!这很有道理,而且效果也很好。我还想问你是否知道有一种方法可以对触摸事件做同样的事情。touchstart/end事件有X,Y吗?@QuantumRich看看这个例子
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 + ")");
finishAngle = angleDeg;