D3.js 惯性阻力布局
我使用最新的d3js和force布局创建交互式图形,如下所示: 要求如下:D3.js 惯性阻力布局,d3.js,D3.js,我使用最新的d3js和force布局创建交互式图形,如下所示: 要求如下: 可以拖动节点(惯性拖动) 节点在碰到边界时反弹 节点彼此不重叠(我可以根据碰撞检测示例进行此操作) 谁来帮我拿1号和2号 这个问题的背景在相关问题中 谢谢。背景 这个答案的背景是在我对一个相关问题的回答中 这个问题是关于为什么节点在释放后会跳回,主要的问题是,在force.drag行为期间,先前的节点位置(d.px,d.py)和当前位置(d.x,d.y)实际上是相反的。因此,当阻力被释放时,初始速度被反转,从而导致跳跃
force.drag
行为期间,先前的节点位置(d.px,d.py)和当前位置(d.x,d.y)实际上是相反的。因此,当阻力被释放时,初始速度被反转,从而导致跳跃行为。这实际上是由于拖动行为在拖动事件中更新以前的位置,以及内部的
力。勾选方法将以前的值复制到每个位置计算的当前值上。(顺便说一句,我相信这是有充分理由的,我怀疑这与…)
惯性拖曳
为了实现惯性拖动,需要校正此速度反转,因此当前和以前的点需要在dragend
之后立即反转
这是一个良好的开端,但还存在一些其他问题:
将上一个位置复制到当前位置时,速度状态将在每个刻度处丢失
“粘性节点”行为(在mouseover
上)在dragend
上重新建立,它倾向于重新捕获节点并消除惯性效应
第一种情况意味着,如果在释放阻力和修正速度之间(即在dragend
之后)出现滴答声,则速度将为零,节点将停止运行。这种情况经常发生,令人讨厌。一种解决方案是维护d3.event.dx
和d3.event.dy
的记录,并使用它们在dragend
上修改(d.px,d.py)。这也避免了由先前点和当前点反转引起的问题
剩下的第二个问题可以通过将粘性节点行为恢复延迟到mouseout
之后来解决。如果鼠标在mouseout
后立即重新进入节点,则建议在mouseout
后稍微延迟
植入
实现上述两个更正的基本策略是在前者中挂钩force布局中的拖动事件,在后者中挂钩force布局中的鼠标事件。出于防御原因,各种挂钩的标准回调存储在节点的数据对象上,并在取消挂钩时从那里检索
在代码中,摩擦参数被设置为1,这意味着它们无限期地保持速度,为了看到稳定的惯性效应,将其设置为0.9。。。我喜欢那些弹跳的球
$(函数(){
可变宽度=1200,
高度=800;
变量圆=[{
x:宽度/2+100,
y:高度/2,
半径:100
}, {
x:宽度/2-100,
y:高度/2,
半径:100
}, ],
nodeFill=“#006E3C”;
var-force=d3.layout.force()
.重力(0)
。收费(-100)
.摩擦(1)
.尺寸([宽度、高度])
.节点(圆)
.linkDistance(250)
.联系强度(1)
.on(“滴答”,滴答)
.start();
滑块控制(“摩擦滑块”,“摩擦力”,力摩擦,[0,1],“,.3f”);
var svg=d3.选择(“主体”)
.append(“svg”)
.attr(“宽度”,宽度)
.attr(“高度”,高度)
.风格(“背景色”、“白色”);
var nodes=svg.selectAll(“.node”);
节点=节点。数据(圆);
nodes.exit().remove();
var enterNode=nodes.enter().append(“g”)
.attr(“类”、“节点”)
.呼叫(强制拖动);
console.log(enterNode);
//将圆添加到组中
enterNode.append(“圆”)
.attr(“r”,函数(d){
返回d.radius;
})
.style(“填充”,“#006E3C”)
.样式(“不透明度”,0.6);
;
(功能(d3,力){
//阻力特性///////////////////////////////////////////////////////////////////
//钩阻力特性
//速度
//保持速度状态,以防在牵引前立即出现力滴答声
//勾号会清除上一个位置
var dragVelocity=(函数(){
var-dx,dy;
函数f(d){
if(d3.事件){
dx=d3.event.dx;
dy=d3.event.dy;
}
返回{
dx:dx,
戴:戴
}
};
f、 正确=功能(d){
//出现勾号并将px/y设置为x/y,重新建立速度状态
d、 px=d.x-dx;
d、 py=d.y-dy;
}
f、 重置=函数(){
dx=dy=0
}
返回f;
})()
//牵引起动钩
var stdDragStart=force.drag().on(“dragstart.force”);
force.drag().on(“dragstart.force”,myDragStart);
函数myDragStart(d){
var=这个,
节点=d3。选择(此);
非粘性鼠标();
dragVelocity.reset();
stdDragStart.call(this,d)
函数nonStickyMouse(){
如果(!d.\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu{
//节点未钩住
//钩子鼠标盖/////////////////////////
//删除鼠标悬停行为上的粘性节点并保存侦听器
d、 _uuuumouseover_force=node.on(“mouseover.force”);
on(“mouseover.force”,null);
d、 _uuumouseout_force=node.on(“mouseout.force”);
d、 _uuuuuuuuuuuuuuhooked=真;
//标准鼠标输出将清除d
d、 打电话给(那个,d);
}
//可拆卸鼠标器/////////////////////////
node.on(“mouseout.force”,null);
}
}
//牵引钩
var stdDrag=force.drag().on(“drag.force”);
force.drag()打开(“拖动”。