数据处理后,d3 会为数据集生成增量 ID,而不是继续使用相同的 ID 号

After data manipulation d3 is generating an incremental id for the data set instead of continuing with the same id numbers

提问人:gyan mishra 提问时间:1/31/2023 更新时间:1/31/2023 访问量:39

问:

这里尝试制作一个数据树,以便每当用户单击任何元素时,必须从数据集中删除该元素,并且该树将再次重新生成。

例如,在单击

enter image description here

假设单击 P3 后,生成的新图是

enter image description here

生成图形的代码是

const svg = d3.select("body").append('svg');

const margin = { left: 80, right: 20, top: 20, bottom: 20 }

var NODES;

const height = 700 - margin.top - margin.bottom;
const width = 800 - margin.left - margin.right;

const nodeElements = [];


let treeData = { id: 0, name: 'p0', children: [{ id: 1, name: 'p1', children: [{ id: 3, name: 'p3', children: [] },] }, { id: 2, name: 'p2', children: [{ id: 4, name: 'p4', children: [] },] }] };

let duration = 1513;
let i = 0;
let root;

let treemap = d3.tree().size([height, width])

svg.attr('height', height + margin.top + margin.bottom)
    .attr('width', width + margin.right + margin.left)
    .append('g')
    .attr('transform', `translate(${margin.left},${margin.top})`)

root = d3.hierarchy(treeData, (d) => {
    console.log(d);
    return d.children;
})

root.x0 = height / 2;
root.y0 = 0;

console.log('ROOT::', root);

update(root);


function update(source) {
    let treedata = treemap(root);
    let nodes = treedata.descendants();

    NODES = nodes;

    nodes.forEach(d => {
        d.y = d.depth * width / 5;
    });
    let node = svg.selectAll("g.node").data(nodes, (d) => d.id || (d.id = ++i));

    // links
    function diagonal(s, d) {
        path = `M ${s.y} ${s.x}
                C ${(s.y + d.y) / 2} ${s.x}
                  ${(s.y + d.y) / 2} ${d.x}
                  ${d.y} ${d.x}`;
        return path;
    }
    let links = treedata.descendants().slice(1);
    let link = svg.selectAll('path.link').data(links, (d) => {
        return d.id;
    })
    let linkEnter = link
        .enter()
        .insert('path', 'g')
        .attr('class', 'link')
        .attr('d', (d) => {
            let o = { x: source.x0, y: source.y0 + 40 }
            return diagonal(o, o)
        })
    let linkUpdate = linkEnter.merge(link);
    linkUpdate
        .transition()
        .duration(duration)
        .attr("d", (d) => {
            return diagonal(d, d.parent);
        });

    let linkExit = link
        .exit()
        .transition()
        .attr('d', (d) => {
            let o = { x: source.x0, y: source.y0 }
            return diagonal(o, o);
        })
        .remove();

    let nodeEnter = node
        .enter()
        .append("g")
        .attr("class", "node")
        .attr("transform", d => {
            return `translate(${source.y0 + 20},${source.x0})`
        })
        .on("click", clicked);


    nodeEnter.append('circle')
        .attr('class', 'node')
        .attr('r', 0)
        .style('fill', d => {
            return d._children ? "red" : "white";
        })


    let nodeUpdate = nodeEnter.merge(node);

    nodeUpdate.transition()
        .duration(duration)
        .attr("transform", d => `translate(${d.y + 20},${d.x})`)
        .attr("opacity", 1)

    nodeUpdate.select("circle.node")
        .attr('r', 10)
        .style("fill", d => d._children ? "red" : "black")
        .attr("cursor", "pointer");

    nodeUpdate.append('rect')
        .attr('x', 0)
        .attr('y', -20)
        .attr('rx', 5)
        .attr('ry', 5)
        .attr('width', 80)
        .attr('height', 40)
        .attr('fill', 'grey')
        
    nodeUpdate.append('text')
        .attr('x', 0)
        .attr('y', 0)
        .attr('dx', 10)
        .text(d => {
            console.log(d.data.name)
            return d.data.name;
        });


    nodeExit = node.exit()
        .transition()
        .duration(duration)
        .attr("transform", function () { return `translate(${source.y + 20},${source.x})` })
        .attr("opacity", 0.5)
        .remove();


    // collapsing of the nodes
    nodes.forEach(d => {
        d.x0 = d.x;
        d.y0 = d.y;
    })

}

function clicked(event, d) {
    let child;
    
    child = childrenCollector(d.id - 1, treeData.children)

    root = d3.hierarchy(treeData, (da) => {
        return da.children;
    })

    console.log("MANIPULATED:::", root)

    root.x0 = height / 2;
    root.y0 = 0;

    update(root);
}

function childrenCollector(sourceId, nestedArray) {
    const i = nestedArray.findIndex(({ id }) => id === sourceId);
    let found;
    if (i > -1) [found] = nestedArray.splice(i, 1)
    else nestedArray.some(({ children }) =>
        found = childrenCollector(sourceId, children)
    );
    return found;
}

面临的问题是,一旦它生成了新结构,新结构就不会被修改。

REASON:::: 在 clicked() 函数的“d.id”处,当首先单击元素时,id 值等于数据中给出的 id,但在修改后,当我单击“d.id”值时,该值会不断增加。为什么会这样,即使我在新数据集上生成图形

JavaScript D3.js 可视化 数据操作

评论


答: 暂无答案