Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/401.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 根据范围滑块的用户输入重新启动d3模拟_Javascript_D3.js_Force Layout_D3 Force Directed - Fatal编程技术网

Javascript 根据范围滑块的用户输入重新启动d3模拟

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

我正在使用布局构建一个“spring”。我想通过用户输入操作它的属性,如“强度”和“距离”。为此,我目前正在使用“输入范围滑块”。为了更好地理解,我制定了一份关于codepen的工作草案,其中该问题涉及:

HTML:

<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);