如何使d3.js强制布局重力矩形?
How to make d3.js force layout gravity rectangular?
在d3.js强制布局中,给定重力值使布局呈圆形。
但是,我想将力布局设为矩形,而节点带有负电荷并且 均匀距离 。 (如上)
有什么方法可以使力布局为矩形吗?
我可以通过修改tick函数来实现吗?
这是我的代码:
var background = d3.select('.background');
var width = background.node().getBoundingClientRect().width,
height = background.node().getBoundingClientRect().height;
var nodes = d3.range(50).map(function(d, i) {
return {
text: "Hello"
};
});
var messages = background.selectAll('.message')
.data(nodes)
.enter()
.append('div')
.attr('class', 'message')
.text(d => d.text)
.each(function(d, i) {
d.width = this.getBoundingClientRect().width;
d.height = this.getBoundingClientRect().height;
});
var force = d3.layout.force()
.gravity(1/88)
.charge(-50)
.nodes(nodes)
.size([width, height]);
messages.call(force.drag);
force.on('tick', function(e) {
messages.each(d => {
d.x = Math.max(0, Math.min(width - d.width, d.x));
d.y = Math.max(0, Math.min(height - d.height, d.y));
});
messages.style('left', d => `${d.x}px`)
.style('top', d => `${d.y}px`);
});
force.start();
body {
padding: 0;
margin: 0;
}
.background {
width: 100%;
height: 100vh;
border: 1px solid #007aff;
}
.message {
display: inline-block;
font-family: sans-serif;
border-radius: 100vh;
color: white;
padding: 10px;
background-color: #007aff;
position: absolute;
}
.boundary {
display: inline-block;
width: 10px;
height: 10px;
background-color: red;
position: absolute;
}
<script src="https://d3js.org/d3.v3.min.js"></script>
<body>
<div class="background">
</div>
</body>
好的,编辑 3:在 d3v4 中,forceCollide 可用于设置节点之间的最小距离,如果您随后使用正强度,这会将节点拉到一起,有助于将它们设置为均匀的距离(尽管圆形比矩形看起来更好):
var force = d3.forceSimulation(nodes)
.force("charge", d3.forceManyBody().strength(-10))
.force("collide", d3.forceCollide(30).strength(1).iterations(1))
.force('x', d3.forceX(width/2).strength(0.5))
.force('y', d3.forceY(height/2).strength(10));
假设节点位于矩形 svg 中,将它们限制在 SVG 的中心内可以帮助平衡边缘:
position.nodes(nodes).on('tick', function ticks() {
nodes.attr("cx", function(d) {
return d.x = Math.max(20, Math.min(width + 20, d.x))
}).attr("cy", function(d) {
return d.y = Math.max(20, Math.min(height + 20, d.y));
})
});
玩弄力的强度可以帮助将它们沿 y 轴吸引:
var position = d3.forceSimulation(nodes).force("charge", d3.forceManyBody())
.force('x', d3.forceX(width/2).strength(1))
.force('y', d3.forceY(height/2).strength(5));
v4 中的力量似乎比 v3 中的自定义更多,我认为 forceCollide 将一些变通方法集成到库中。因此,您可以尝试找到 v3 解决方法,或者考虑升级到 v4。
在 v3 中,我尝试使用重力、电荷和限制 x 和 y 来更好地保持盒子中的节点,fiddle here.但是我对 v3 的了解还不够多,无法改进它那。
在d3.js强制布局中,给定重力值使布局呈圆形。
有什么方法可以使力布局为矩形吗?
我可以通过修改tick函数来实现吗?
这是我的代码:
var background = d3.select('.background');
var width = background.node().getBoundingClientRect().width,
height = background.node().getBoundingClientRect().height;
var nodes = d3.range(50).map(function(d, i) {
return {
text: "Hello"
};
});
var messages = background.selectAll('.message')
.data(nodes)
.enter()
.append('div')
.attr('class', 'message')
.text(d => d.text)
.each(function(d, i) {
d.width = this.getBoundingClientRect().width;
d.height = this.getBoundingClientRect().height;
});
var force = d3.layout.force()
.gravity(1/88)
.charge(-50)
.nodes(nodes)
.size([width, height]);
messages.call(force.drag);
force.on('tick', function(e) {
messages.each(d => {
d.x = Math.max(0, Math.min(width - d.width, d.x));
d.y = Math.max(0, Math.min(height - d.height, d.y));
});
messages.style('left', d => `${d.x}px`)
.style('top', d => `${d.y}px`);
});
force.start();
body {
padding: 0;
margin: 0;
}
.background {
width: 100%;
height: 100vh;
border: 1px solid #007aff;
}
.message {
display: inline-block;
font-family: sans-serif;
border-radius: 100vh;
color: white;
padding: 10px;
background-color: #007aff;
position: absolute;
}
.boundary {
display: inline-block;
width: 10px;
height: 10px;
background-color: red;
position: absolute;
}
<script src="https://d3js.org/d3.v3.min.js"></script>
<body>
<div class="background">
</div>
</body>
好的,编辑 3:在 d3v4 中,forceCollide 可用于设置节点之间的最小距离,如果您随后使用正强度,这会将节点拉到一起,有助于将它们设置为均匀的距离(尽管圆形比矩形看起来更好):
var force = d3.forceSimulation(nodes)
.force("charge", d3.forceManyBody().strength(-10))
.force("collide", d3.forceCollide(30).strength(1).iterations(1))
.force('x', d3.forceX(width/2).strength(0.5))
.force('y', d3.forceY(height/2).strength(10));
假设节点位于矩形 svg 中,将它们限制在 SVG 的中心内可以帮助平衡边缘:
position.nodes(nodes).on('tick', function ticks() {
nodes.attr("cx", function(d) {
return d.x = Math.max(20, Math.min(width + 20, d.x))
}).attr("cy", function(d) {
return d.y = Math.max(20, Math.min(height + 20, d.y));
})
});
玩弄力的强度可以帮助将它们沿 y 轴吸引:
var position = d3.forceSimulation(nodes).force("charge", d3.forceManyBody())
.force('x', d3.forceX(width/2).strength(1))
.force('y', d3.forceY(height/2).strength(5));
v4 中的力量似乎比 v3 中的自定义更多,我认为 forceCollide 将一些变通方法集成到库中。因此,您可以尝试找到 v3 解决方法,或者考虑升级到 v4。
在 v3 中,我尝试使用重力、电荷和限制 x 和 y 来更好地保持盒子中的节点,fiddle here.但是我对 v3 的了解还不够多,无法改进它那。