- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个包含父节点和子节点的数据集。父节点可以与其他父节点链接,子节点可以与它们的父节点链接。我想要做的是将子节点径向放置在父节点周围。节点看起来像这样
parent: [{
id: 1,
type: 'parent',
x: ,
y: ,
vx: ,
vy: ,
}, {
id: 2
x: ,
y: ,
vx: ,
vy: ,
}]
child: [{
id: 1,
type: 'child',
parent_node: {
id: 1,
x: ,
y: ,
vx: ,
vy: ,
},
x: ,
y: ,
vx: ,
vy: ,
}]
所以我有父节点的详细信息,例如子节点内的 x 和 y。
我尝试动态分配 x
和 y
(如中间所示),但找不到方法:
force('radial', d3.forceRadial()
.radius(node => {
if (node.type === 'child') {
return 10
}
return 0
})
.x(node => {
if (node.type === 'child') {
return node.parent_node.x
}
return 0
})
.y(node => {
if (node.type === 'child') {
return node.parent_node.y
}
return 0
})
)
这样的事情能做吗?以便可以根据父节点的位置动态提供每个子节点的中心?
最佳答案
前段时间我创建了一个 d3.forceRadial
版本,它接受一个用于设置 x
和 y
位置的函数。你可以看到 pull request here , 和 code is here
这个 pull request 还没有被接受,考虑到它是一个很老的请求并且没有来自 Mike Bostock(D3 的创建者)的评论,我认为它永远不会被接受。因此,如果需要,您可以通过复制链接中的函数来使用此自定义 d3.forceRadial
:https://pastebin.com/75j8vj3C
然后,只需使用带有自定义力的定位函数,如下所示:
simulation.force("radial", customRadial(radius, foo, bar))
//positioning functions--------------------------^----^
或者:
simulation.force("radial", customRadial()
.radius(radius)
.x(foo)
.y(bar))
foo
和 bar
是您在 x
和 y
位置的函数。
这是一个演示:
var svg = d3.select("body")
.append("svg")
.attr("width", 600)
.attr("height", 200);
var data = d3.range(500).map(function(d) {
return {
node: "foo" + d,
centerX: 100 + ~~((d / 100) % 20) * 100
}
});
var simulation = d3.forceSimulation(data)
.force("radius", customRadial().radius(40)
.x(function(d) {
return d.centerX
})
.y(100)
.strength(1))
.force("collide", d3.forceCollide().radius(3).strength(.8));
var nodes = svg.selectAll(null)
.data(data)
.enter()
.append("circle")
.attr("r", 2.5)
.style("fill", "teal")
simulation.on("tick", tick);
function tick() {
nodes.attr("cx", function(d) {
return d.x
})
.attr("cy", function(d) {
return d.y
});
}
function customRadial(radius, x, y) {
var constant = function(x) {
return function() {
return x;
};
};
var nodes,
strength = constant(0.1),
strengths,
radiuses,
xs,
ys;
if (typeof radius !== "function") radius = constant(+radius);
if (typeof x !== "function") x = constant(x == null ? 0 : +x);
if (typeof y !== "function") y = constant(y == null ? 0 : +y);
function force(alpha) {
for (var i = 0, n = nodes.length; i < n; ++i) {
var node = nodes[i],
dx = node.x - xs[i] || 1e-6,
dy = node.y - ys[i] || 1e-6,
r = Math.sqrt(dx * dx + dy * dy),
k = (radiuses[i] - r) * strengths[i] * alpha / r;
node.vx += dx * k;
node.vy += dy * k;
}
}
function initialize() {
if (!nodes) return;
var i, n = nodes.length;
strengths = new Array(n);
radiuses = new Array(n);
xs = new Array(n);
ys = new Array(n);
for (i = 0; i < n; ++i) {
radiuses[i] = +radius(nodes[i], i, nodes);
xs[i] = +x(nodes[i], i, nodes);
ys[i] = +y(nodes[i], i, nodes);
strengths[i] = isNaN(radiuses[i]) ? 0 : +strength(nodes[i], i, nodes);
}
}
force.initialize = function(_) {
nodes = _, initialize();
};
force.strength = function(_) {
return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initialize(), force) : strength;
};
force.radius = function(_) {
return arguments.length ? (radius = typeof _ === "function" ? _ : constant(+_), initialize(), force) : radius;
};
force.x = function(_) {
return arguments.length ? (x = typeof _ === "function" ? _ : constant(+_), initialize(), force) : x;
};
force.y = function(_) {
return arguments.length ? (y = typeof _ === "function" ? _ : constant(+_), initialize(), force) : y;
};
return force;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
如果您不想(或者出于任何原因不能)使用此自定义代码,一个简单的解决方法是创建多个模拟,每组元素一个,就像我在 this data visualization 做过.
关于javascript - 如何使用函数动态分配 d3.forceRadial 的中心?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54035048/
我试图让 d3.forceRadial() 围绕它们各自的父级分层分布节点,但是当我在 force 上设置 x 和 y 参数时,所有节点都向右下角射出并超出 x 和y 值以万位结尾.. 我的代码是这样
我有一个包含父节点和子节点的数据集。父节点可以与其他父节点链接,子节点可以与它们的父节点链接。我想要做的是将子节点径向放置在父节点周围。节点看起来像这样 parent: [{ id: 1,
我是一名优秀的程序员,十分优秀!