D3可缩放打包布局数据更新

时间:2019-06-06 13:16:36

标签: d3.js zoom hierarchy

我试图改编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';
    });

提前谢谢

0 个答案:

没有答案