Javascript D3.js带惯性的拖动

Javascript D3.js带惯性的拖动,javascript,d3.js,Javascript,D3.js,我试图使用d3.js制作带有惯性的拖动,但有一个问题,惯性效果中存在一些视觉冲击,如果圆被快速拖动和释放,这一点尤其明显 理想情况下,它应该像谷歌地图一样工作:当鼠标被释放时,圆圈应该继续在同一方向平稳移动一段时间,然后停止 这里可以找到一些很好的例子,但它是通过更新d3.js的源代码实现的(我想不是官方的),而我对使用d3.js的官方版本实现很感兴趣 有什么建议吗 var svg=d3.选择(“#父项”) .append('svg') .attr('width','100%”) .attr(

我试图使用d3.js制作带有惯性的拖动,但有一个问题,惯性效果中存在一些视觉冲击,如果圆被快速拖动和释放,这一点尤其明显

理想情况下,它应该像谷歌地图一样工作:当鼠标被释放时,圆圈应该继续在同一方向平稳移动一段时间,然后停止

这里可以找到一些很好的例子,但它是通过更新d3.js的源代码实现的(我想不是官方的),而我对使用d3.js的官方版本实现很感兴趣

有什么建议吗

var svg=d3.选择(“#父项”)
.append('svg')
.attr('width','100%”)
.attr(‘高度’、‘100%’);
var g=svg.append('g')
.attr('transform',“translate(450250)scale(1)”);
变量圆=d3。选择('g')
.append('圆')
.attr('class','circle')
.attr('r',20);
函数缩放(){
var transform=d3.event.transform;
g、 属性(“变换”,变换);
}
var mouseEvents=[];
var zoomFunction=d3.zoom().on('zoom',function()){
缩放();
if(d3.event.sourceEvent){
mouseEvents.push(d3.event);
如果(mouseEvents.length>5){
mouseEvents.shift();
}
}
})
.on('end',function(){
if(d3.event.sourceEvent&&mouseEvents.length){
让lastEvent=mouseEvents.shift();
设x1=lastEvent.sourceEvent.pageX;
设y1=lastEvent.sourceEvent.pageY;
设t1=lastEvent.sourceEvent.timeStamp;
设x2=d3.event.sourceEvent.pageX;
设y2=d3.event.sourceEvent.pageY;
设t2=d3.event.sourceEvent.timeStamp;
让心灵距离=20;
//三角洲
变量dX=x2-x1,
dY=y2-y1,
dMs=数学最大值(t2-t1,1);
//速度
var speedX=数学最大值(数学最小值(dX/dMs,1),-1);
var=数学最大值(数学最小值(dY/dMs,1),-1);
//移动的距离(欧几里德距离)
var距离=数学sqrt(数学功率(x1-x2,2)+数学功率(y1-y2,2));
如果(距离>距离){
变量位置=d3.event.transform;
var newLeft=位置x+(速度x*距离*0.6),
newTop=位置y+(速度*距离*0.6);
svg
.transition()
.持续时间(350)
.打电话(
zoomFunction.transform,
d3.zoomIdentity.translate(newLeft,newTop).scale(1)
);
}
}
mouseEvents=[];
});
d3.zoom().translateBy(svg,450250);
d3.zoom().scaleBy(svg,1);
调用(zoomFunction).on('dblclick.zoom',null)
#父级{
宽度:900px;
高度:500px;
}
.圆圈{
填充:蓝色;
}

您可以使用,这是一个处理此问题的软件包。作为灵感,我得到了以下结果:

var位置=[450250];
可变宽度=500,
高度=300,
半径=20;
var svg=d3。选择(“#父项”)
.append('svg')
.attr('width',width)
.attr('高度'),高度;
var g=svg.append('g');
函数绘图(){
g、 attr('transform','translate(${position[0]},${position[1]})`);
}
draw();
变量圆=d3。选择('g')
.append('圆')
.attr('class','circle')
.attr('r',半径);
/*函数将球保持在视图内*/
函数更新位置(新位置、偏移){
如果(偏移量===未定义){
偏移量={x:0,y:0};
}
新位置[0]=数学最大值(半径,数学最小值(新位置[0]+偏移量.x,宽度-半径));
新位置[1]=数学最大值(半径,数学最小值(新位置[1]+偏移量.y,高度-半径));
位置=新位置;
}
函数getTransformParameters(transformString){
var values=transformString.substr(“translate”(.length)
.拆分(“,”)
.地图(功能(d){
返回parseInt(d,10);
});
返回{x:values[0],y:values[1]};
}
变量偏移量={x:0,y:0};
var惯性=d3.0惯性({
开始:函数(){
var-transform=getTransformParameters(g.attr(“transform”);
偏移量={
x:transform.x-惯性位置[0],
y:transform.y-惯性位置[1]
};
},
move:function(){
更新位置(惯性、位置、偏移);
draw();
},
渲染:函数(t){
更新位置([
//速度是恒定的,所以我用t**2使它看起来好像变慢了
//0.25只是让球慢下来,这样球就不会飞出去
惯性位置[0]+0.25*t**2*惯性速度[0],
惯性位置[1]+0.25*t**2*惯性速度[1]
]);
draw();
}
});
svg.call(
d3.阻力()
.on(“启动”,惯性。启动)
.打开(“拖动”,惯性。移动)
.on(“结束”,惯性。结束)
);
#父级{
宽度:900px;
高度:500px;
}
.圆圈{
填充:蓝色;
}


谢谢!d3惯性提供了预期的行为。但我注意到,当开始拖动时,它使圆居中,它来自d3.drag,并使用鼠标作为圆心的坐标。这可能是拖动的预期行为吗?找到了一个适合我的解决方案:事件包含dx和dy值,实际更改元素fr使用“transform”属性,我可以更改元素在此增量上的位置,以获得预期的位置:
。在('drag',函数(){/*getTransformParameters应返回当前元素位置*/const params=getTransformParameters(gElement.attr('transform'));惯性。移动({x:params.width+event.dx,y:params.height+event.dy});})
我会做不同的事情。根据我的经验,在这样一个库中进行黑客攻击是一个产生错误的方法。我已经用一个解决方案更新了我的答案。我计算了变换和惯性之间的差异。只在开始时定位
,然后用这个差异绘制球。这意味着如果你拖动球的左角,如果始终保持在左拐角处。