标签:javascript d3-js force-layout d3v4
我在多焦点布局中有三组节点.每个节点都已经以HTML格式呈现.
我想要做的是当一个事件发生时(在这种情况下是一个下拉列表),节点将自己重新定位到他们的新集群.
我的意思是,如果新数据左边只有10个蓝色,右边有90个红色,中间有2个紫色,左边的蓝色将变为红色并转换到右边的簇.
从我到目前为止所读到的,我认为它可能正在改变引力.但是,我不认为这是D3 V4中的一个选项.
我能找到的最接近的例子是here.
这是我的强制布局代码的样子:
var node = this.svg.selectAll('path')
.data(data);
// foci is a dictionary that assigns the x and y value based
// on what group a node belongs to.
var foci = {
"Blue" : {
"x" : xScale(0),
"y": height / 2
},
"Red": {
"x" : xScale(1),
"y": height / 2
},
"Purple": {
"x" : xScale(2),
"y": height / 2
},
};
// This helped me position the nodes to their assigned clusters.
var forceX = d3.forceX((d) => foci[d.group].x);
var forceY = d3.forceY((d) => foci[d.group].y);
var force = d3.forceSimulation(data)
.force('x', forceX)
.force('y', forceY)
.force("collide", d3.forceCollide(8))
.on('tick', function() {
node
.attr('transform', (d) => {
return 'translate(' + (d.x - 100) + ',' + (-d.y + 25) + ')';
});
});
到目前为止我能够完成的是根据下拉列表中的更改重新绘制布局,重新启动d3.forceSimulation()并使群集快照回到页面上,如下面的gif所示.
那不是我想要的.我正在努力使重新排列尽可能无缝.
更新:通过不重新初始化d3.forceSimulation(),我可以将新数据绑定到节点并更改其颜色.现在只是将它们移动到适当的集群.
解决方法:
您可以使用restart()
简单地重新模拟模拟,而不是重新初始化d3.forceSimulation():
Restarts the simulation’s internal timer and returns the simulation. In conjunction with simulation.alphaTarget or simulation.alpha, this method can be used to “reheat” the simulation during interaction, such as when dragging a node, or to resume the simulation after temporarily pausing it with simulation.stop.
我创建了一个演示,使用部分代码向您展示.在此演示中,按钮随机化每个数据点的颜色.之后,我们重新模拟模拟:
force.alpha(0.8).restart();
检查一下,点击“随机化”:
var width = 500, height = 200;
var svg = d3.select("#svgdiv")
.append("svg")
.attr("width", width)
.attr("height", height);
var data = d3.range(100).map(function(d, i){
return {
group: Math.random()*2 > 1 ? "blue" : "red",
id: i
}
});
var xScale = d3.scaleOrdinal()
.domain([0, 1])
.range([100, width-100]);
var foci = {
"blue" : {
"x" : xScale(0),
"y": height / 2
},
"red": {
"x" : xScale(1),
"y": height / 2
}
};
var forceX = d3.forceX((d) => foci[d.group].x);
var forceY = d3.forceY((d) => foci[d.group].y);
var node = svg.append("g")
.attr("class", "nodes")
.selectAll("circle")
.data(data)
.enter().append("circle")
.attr("r", 5)
.attr("fill", (d)=>d.group);
var force = d3.forceSimulation(data)
.velocityDecay(0.65)
.force('x', forceX)
.force('y', forceY)
.force("collide", d3.forceCollide(8));
force.nodes(data)
.on('tick', function() {
node
.attr('transform', (d) => {
return 'translate(' + (d.x) + ',' + (d.y) + ')';
});
});
d3.select("#btn").on("click", function(){
data.forEach(function(d){
d.group = Math.random()*2 > 1 ? "blue" : "red"
})
node.transition().duration(500).attr("fill", (d)=>d.group);
setTimeout(function(){
force.nodes(data);
force.alpha(0.8).restart();
}, 1500)
})
<script src="https://d3js.org/d3.v4.min.js"></script>
<button id="btn">Randomize</button>
<div id="svgdiv"><div>
PS:我把再加热设置在一个setTimeout中,所以你可以先看到圆圈改变颜色,然后转移到焦点位置.
标签:javascript,d3-js,force-layout,d3v4 来源: https://codeday.me/bug/20190527/1165402.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。