Обновление масштабируемых данных D3 с масштабированием - PullRequest
0 голосов
/ 06 июня 2019

Я попытался адаптировать пример упаковки с масштабируемым кругом от Майка Бостока.https://observablehq.com/@d3/zoomable-circle-packing

Я переписал пример в очень простой компонент реагирования и попытался динамически обновлять узлы.

Но, например, когда я добавляю узел в качестве дочернего узла корневого узла,нарушена функция масштабирования (только последний добавленный узел летает, но масштабируется неправильно).

Может кто-нибудь помочь мне с этой проблемой?Я хотел бы добавить и удалить узлы из макета.

Я загрузил весь пример здесь: 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';
    });

Спасибозаранее

...