我正在尝试渲染一个d3js部队模拟,但我想确保我的节点不会传递错误信息。
下面的代码用于显示节点,但由于力布局的动态性质,它偶尔会将一些节点从其适当的x坐标位置推开。
inOrder(){
this.simulation
.force("x", d3.forceX(d => this.xScale(d.value)))
.force("y", d3.forceY(this.height / 2))
.alpha(1).restart();
},这是一个惊人的例子:数字应该从左到右依次排列。

我尝试使用节点上的fx属性锁定位置:
inOrder(){
this.releases.forEach(x => {
x.fx = this.xScale(x.value)
})
this.simulation
.force("x", d3.forceX(d => this.xScale(d.value)))
.force("y", d3.forceY(this.height / 2))
.alpha(1).restart();
},

这样做的目的是保持x位置,但是当调用inOrder方法时,节点立即跳到最后的x位置。这破坏了力模拟的流体和动态性质。
有没有办法让这两个世界都发挥最大的作用?也许通过使用.on("end", () => {})或.on("tick", () => {})?事件处理程序?
迈克·博斯托克(https://stackoverflow.com/users/365814/mbostock)和单卡特创作了一些作品,作为我在这里所要做的事情的灵感来源:
单击“更改”和“部门汇总”选项卡https://archive.nytimes.com/www.nytimes.com/interactive/2012/02/13/us/politics/2013-budget-proposal-graphic.html?hp
单击“整个图片与按行业选项卡查看”之间的https://archive.nytimes.com/www.nytimes.com/interactive/2013/05/25/sunday-review/corporate-taxes.html
发布于 2019-05-29 19:51:22
我在这里可能遗漏了一些东西,但是对x定位力(和y)的强度进行修补可以帮助确保您的订单正确完成。forceX或forceY的默认强度为0.1,强度实现如下:
值0.1表示每个应用程序节点应该将其当前x位置的十分之一移动到目标x位置。较高的值更快地将节点移动到目标位置,通常以牺牲其他力量或约束为代价。不建议在0,1范围外设置值。(文档)
因此,我们可以增加forceX强度,并且为了使x轴上的节点更自由地移动,我们可以减少forceY --允许节点更容易地跳跃--降低碰撞强度也会有帮助。
我不给下面的圆圈贴上标签(相反,它们是顺序阴影的),但我确实运行了一次检查,看看它们是否整齐(在模拟结束时,日志用于控制台),下面的代码片段只修改x和y力(而不是碰撞力):

var height = 300;
var width = 500;
var data = d3.range(30).map(function(d,i) {
return { size: Math.random()+1, index: i}
});
var svg = d3.select("body")
.append("svg")
.attr("width",width)
.attr("height",height);
var x = d3.scaleLinear()
.domain([1,30])
.range([50,width-50]);
var color = d3.scaleLinear()
.domain([0,29])
.range(["#ccc","#000"])
var simulation = d3.forceSimulation()
.force("x", d3.forceX(d => x(d.index)).strength(0.20))
.force("y", d3.forceY(height / 2).strength(0.05))
.force("collide", d3.forceCollide().radius(d=> d.size*10))
.alpha(1).restart();
var circles = svg.selectAll(null)
.data(data)
.enter()
.append("circle")
.attr("r", function(d) { return d.size * 10; })
.attr("fill", function(d,i) { return color(i); })
simulation.nodes(data)
.on("tick",tick)
.on("end",verify);
function tick() {
circles
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; })
}
function verify() {
var n = 0;
for(var i = 0; i < data.length - 1; i++) {
if(data[i].x > data[i+1].x) n++;
}
console.log(n + " out of place");
}<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
这个片段将30个圆圈放置在500x300区域中,没有太多的问题:我已经测试了几次,其中0不合适。在这里放置100个圆圈会引起问题:在这样狭小的区域内,圆圈将无法改变位置:可能需要进一步修改兵力,但更大的地块可能会优先考虑(而不是小片段视图)。
另一种选择是在整个模拟过程中修改力:先以强x力和低碰撞力开始,然后慢慢拨起碰撞,以使随后的碰撞最小化。下面是修改示例函数中的作用力的一个例子--这个例子是为了链接长度,而不是放在x上--但是适配应该不会太难。
另一种可能性是保持α高,直到所有的圆都在x轴上被正确的排列,然后开始冷却,这将再次发生在滴答函数中。
https://stackoverflow.com/questions/56366666
复制相似问题