D3:从元素绘制中分离数据退出/删除/合并

时间:2017-07-03 09:18:26

标签: javascript d3.js svg

我正在使用D3 v4绘制一些复杂的交互式SVG并遇到一些问题。我的目标是:

  • 每个数据元素对应于具有多个SVG形状元素的组(例如<g><circle></circle><circle></circle></g>
  • 必须按特定顺序绘制多个SVG形状元素(因为它们重叠)
  • 更新某些形状元素而不添加或删除数据元素(例如,单击形状时,更改形状颜色)

我遇到了麻烦,因为.data() - &gt; .exit().remove() - &gt; .enter() - &gt; .merge()进程需要特定的顺序,该顺序与必要的绘制顺序冲突,以及动态更新样式的能力。这是我开始使用的,由于绘制顺序不起作用:

function updateGraph() {
    let eachNodeG = allNodesG
        .selectAll('.eachNodeG')
        .data(graphData._nodes, function (d) {
            return d._id;
        })

    eachNodeG.exit().remove();

    let eachNodeGEnter = eachNodeG.enter()
        .append('g')
        .attr("class", "eachNodeG")

    eachNodeGEnter
        .append('circle')
        .classed('interactivecircle', true)
        .on('click', function (d) {...})

    let eachNodeG = eachNodeGEnter
        .merge(eachNodeG)
        .style('fill', function (d) {...}) //this is here b/c it needs to change
            // when data change (without them being added/removed)

    // this must be separate because the background circle needs to change even
    // when nodes are not added and removed; but this doesn't work here because
    // the circle needs to be in the background
    eachNodeG
        .append('circle')
        .classed('bgcircle', true)
}

我想也许我可以完全将数据更新过程与数据绘制过程分开,只需对包含数据的组执行enter() exit() merge(),然后再绘制所有内容。但在这里我遇到了一个不同的问题:要么我删除并重新添加每个更新的所有形状(这使双击很困难,似乎浪费处理能力),或者我必须找出一些方法来更新只有已经改变的形状。是否使用remove和re-add方法如下所示:

// add/remove individual groups based on updated data
let eachNodeG = allNodesG
    .selectAll('.eachNodeG')
    .data(graphData._nodes)

eachNodeG.exit().remove();

let eachNodeGEnter = eachNodeG.enter()
    .append('g')
    .attr("class", "eachNodeG")

eachNodeG = eachNodeGEnter
    .merge(eachNodeG)

// draw (or remove and re-draw) elements within individual groups
d3.selectAll('.bgcircle').remove()

eachNodeG.append('circle')
    .classed('bgcircle', true)

d3.selectAll('.interactivecircle').remove()

eachNodeG.append('circle')
    .classed('interactivecircle', true)
    .style('fill', function (d) {...})
    .on('click',function(d){...})
})

是否有更好的方法来按顺序绘制形状,同时保持它们的可更新性?

1 个答案:

答案 0 :(得分:1)

您可以使用selection.raiseselection.lower在圈子创建后移动。