Javascript 根据范围滑块的用户输入重新启动d3模拟
我正在使用布局构建一个“spring”。我想通过用户输入操作它的属性,如“强度”和“距离”。为此,我目前正在使用“输入范围滑块”。为了更好地理解,我制定了一份关于codepen的工作草案,其中该问题涉及: HTML:Javascript 根据范围滑块的用户输入重新启动d3模拟,javascript,d3.js,force-layout,d3-force-directed,Javascript,D3.js,Force Layout,D3 Force Directed,我正在使用布局构建一个“spring”。我想通过用户输入操作它的属性,如“强度”和“距离”。为此,我目前正在使用“输入范围滑块”。为了更好地理解,我制定了一份关于codepen的工作草案,其中该问题涉及: HTML: <input id="strengthElem" step="0.1" type="range" min="0" max="2"/> 现在,当与范围滑块发生交互时,我想重新启动或重新计算d3.simulation对象。这是我当前的模拟: let simulation
<input id="strengthElem" step="0.1" type="range" min="0" max="2"/>
现在,当与范围滑块发生交互时,我想重新启动或重新计算d3.simulation对象。这是我当前的模拟:
let simulation = d3.forceSimulation().nodes(nodes)
.force("link", d3.forceLink()
.id(function(d) { return d.index; })
.strength(function(d) { return 2; })
.distance(function(d) { return 2; }))
.force("charge", d3.forceManyBody());
对于强度和距离,这些值目前是硬编码的。我想将其更改为,例如:
.strength(function(d) { return strength; })
.distance(function(d) { return distance; })
我试图设置d3.call().on()函数,但无法使其正常工作。我想知道如何基于unser输入操作模拟,这发生在force()函数之外/svg容器之外
遗憾的是,我无法让某些东西工作,我不知道如何设置一个适当的d3事件侦听器,该侦听器对输入按钮作出反应,然后根据更改的值重新计算强制布局。有什么想法吗?一种方法是删除svg的内容,然后用所需的常量重新绘制它 我不明白你在哪里被卡住了,因为我只是像你在问题中说的那样改变了几行 在单击处理程序中,我清除了svg的内容,并调用了“draw”函数:
strengthElem.addEventListener('click', function(evt) {
strength = strengthElem.value;
console.log('strength', strength);
d3.select('svg').selectAll("*").remove();
force(route);
}, false);
已将配置变量移动到全局范围:
var distance = 1;
let distElem = window.document.getElementById('distanceElem');
let strengthElem = window.document.getElementById('strengthElem');
var strength = strengthElem.value;
distance = distElem.value;
正如您所说,我已更改为返回参数:
.strength(function(d) { return strength; })
.distance(function(d) { return distance; }))
完整示例:您应该首先创建力,然后将引用传递给模拟,而不是在不保留力的情况下创建链接力。这样,您以后就可以根据滑块的值操纵力:
// Create as before, but keep a reference for later manipulations.
let linkForce = d3.forceLink()
.id(function(d) { return d.index; })
.strength(2)
.distance(2);
let simulation = d3.forceSimulation().nodes(nodes)
.force("link", linkForce)
.force("charge", d3.forceManyBody());
在滑块上注册事件处理程序时,您可能还希望使用d3.select()
,以便于使用,并使用指定函数
在处理函数中,该
指向实际的DOM元素,从而允许轻松访问滑块的值。现在可以使用先前保留的参考来更新连接力的参数。剩下要做的就是重新加热模拟以继续其计算
请查看此代码片段以获得一个有效的演示:
“严格使用”;
var route=[[30,30]、[192172]、[194170]、[197167]、[199164]、[199161]、[199157]、[199154]、[199150]、[199147]、[199143]、[199140]、[200137]、[202134]、[204132]、[207129]、[207126]、[200200];
设距离=1;
让createNode=函数(id,coords){
返回{
半径:4,
x:coords[0],
y:coords[1],
};
};
让getNodes=(路由)=>{
设d=[];
设i=0;
route.forEach(功能(协调){
if(i==0 | | i==route.length-1){
d、 push(createNode(i,coord));
d[i].fx=coord[0];
d[i].fy=coord[1];
}
否则{
d、 push(createNode(i,coord));
}
++一,;
});
返回d;
};
让getLinks=(节点)=>{
设next=1;
设prev=0;
设obj=[];
while(下一个
.link{
行程:777;
笔画宽度:2px;
}
.连接线{
行程:#999;
笔划不透明度:0.6;
}
.节点圆{
冲程:#fff;
笔划宽度:1.5px;
}
力量
距离
谢谢你的帮助!我在d3的第一个项目中,我想我在几十个例子中迷失了方向,寻找一个能解决我问题的例子。我在github上搜索,寻找类似d3事件处理程序的东西,它可以执行类似simulation.restart()的操作。经过数小时的搜索,我认为这个问题不会那么难,我认为我遗漏了一些东西:)。也许应该有更好的解决方案,关于这个问题,迈克·博斯特斯托克(Mike Boststock)说。他说移除节点是你永远不想做的事情。有没有办法修改模拟对象内部的力的强度,这样我们就不需要删除节点、重新计算,然后再将它们添加回svg?@bitHugger wow:D检查alt
// Create as before, but keep a reference for later manipulations.
let linkForce = d3.forceLink()
.id(function(d) { return d.index; })
.strength(2)
.distance(2);
let simulation = d3.forceSimulation().nodes(nodes)
.force("link", linkForce)
.force("charge", d3.forceManyBody());
d3.select('#strengthElem')
.on('click', function() {
// Set the slider's value. This will re-initialize the force's strenghts.
linkForce.strength(this.value);
simulation.alpha(0.5).restart(); // Re-heat the simulation
}, false);
d3.select('#distanceElem')
.on('click', function(evt) {
// Set the slider's value. This will re-initialize the force's strenghts
linkForce.distance(this.value);
simulation.alpha(0.5).restart(); // Re-heat the simulation
}, false);