我试图改编Mike Bostock的可缩放圆形包装示例。 https://observablehq.com/@d3/zoomable-circle-packing
我已将示例重写为一个非常简单的react组件,并尝试动态更新节点。
但是例如当我将一个节点添加为根节点的子节点时,缩放功能被破坏(只有最后一个添加的节点飞来飞去,但没有正确缩放)。
有人可以帮助我解决这个问题吗? 我想从布局中添加和删除节点。
我在此处上传了整个示例: https://github.com/bbraeu/zoomable_circle_packing
一些示例代码
数据准备:
this.pack = d3
.pack()
.size([ this.state.diameter - this.state.margin, this.state.diameter - this.state.margin ])
.padding(this.state.margin);
this.root = d3.hierarchy(this.data).sum((d) => 1).sort((a, b) => {
return b.value - a.value;
});
this.nodes = this.pack(this.root);
this.view = [ this.root.x, this.root.y, this.root.r + this.state.margin ];
DrawNodes功能:
this.circle = this.g
.selectAll('circle')
.data(this.nodes.descendants())
.enter()
.append('circle')
.attr('class', (d) => {
return d.parent ? 'node' : 'node node--root';
})
.style('fill', (d) => {
return d.children ? this.color(d.depth) : 'white';
})
.on('click', (d) => {
if (this.focus !== d) this.zoom(d);
d3.event.stopPropagation();
});
this.zoomTo([ this.view[0], this.view[1], this.view[2] * 2 + this.state.margin ], this.root);
ZomomTo函数:
this.view = v;
this.currentDepth = node.depth;
this.circle
.attr('transform', (d) => {
return (
'translate(' +
(d.x - this.view[0]) * this.state.diameter / this.view[2] +
',' +
(d.y - this.view[1]) * this.state.diameter / this.view[2] +
')'
);
})
.attr('r', (d) => {
return d.r * this.state.diameter / this.view[2];
});
缩放功能:
this.focus = d;
var focus = this.focus;
var transition = d3.transition().duration(d3.event.altKey ? 7500 : 750).tween('zoom', (d) => {
var i = d3.interpolateZoom(this.view, [ this.focus.x, this.focus.y, this.focus.r * 2 + this.state.margin ]);
return (t) => {
this.zoomTo(i(t), this.focus);
};
});
transition
.selectAll('text')
.filter(function(d) {
return d.parent === focus || this.style.display === 'inline';
})
.transition(transition)
.style('fill-opacity', (d) => (d.parent === focus ? 1 : 0))
.on('start', function(d) {
if (d.parent === focus) this.style.display = 'inline';
})
.on('end', function(d) {
if (d.parent !== focus) this.style.display = 'none';
});
提前谢谢