D3 v4重新渲染嵌套对象,而enter()和exit()有问题

时间:2018-07-11 12:10:24

标签: javascript d3.js

我正在尝试显示包裹在<g>元素中的许多圆圈。这个包裹性的东西对我很重要,因为在现实世界中,我也希望其他元素也加入我的团队。问题是,下面的示例中的圆圈不会在第一次render(myObjects)调用中显示,并且如果您按下 render 按钮,则会显示它们。

第二个问题是,当我按下 update 时,先前绘制的圆没有被删除,而新绘制的圆将在其上方呈现。

var svg = d3.select('body').append('svg')
        .attr('width', 250)
        .attr('height', 250);

    //render the data
    function render(datum) {
        //Bind 
        var groups = svg.selectAll("g").data(datum);
        groups.enter().append('g');

        var circles = groups.append("circle").attr('r', 10)
            .attr('cx', function(d) {
                return d.x;
            })
            .attr('cy', function(d) {
                return d.y;
            });

        groups.exit().remove();
    }

    var myObjects = [{ x: 100, y: 100 }, { x: 130, y: 120 }, { x: 80, y: 180 }, { x: 180, y: 80 }, { x: 180, y: 40 }];
    var newObjects = [{ x: 200, y: 120 }, { x: 150, y: 160 }, { x: 20, y: 80 }, { x: 80, y: 60 }, { x: 100, y: 20 }];

    function removeEls() {
        svg.selectAll('circle').remove();
    }

    render(myObjects);
svg {
    width: 500px;
    height: 500px
}

button {
    float: left
}

text {
    text-anchor: middle;
}

circle {
    fill: orange;
    stroke: orange;
    fill-opacity: 0.5;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<button onclick="render(newObjects)">Update</button>
<button onclick="render(myObjects);">Render</button>
<button onclick="removeEls();">removeEls</button>

1 个答案:

答案 0 :(得分:0)

您的代码中有2个小问题:

  1. 您已在groups中添加了圆圈,而不是在groups.enter()中添加了圆圈,因此在第一次绘制时不显示圆圈的问题
  2. 添加数据时,您忘记添加标识符,因此脚本无法检测到哪些是新数据,哪些不是。我添加了一个d.x / d.y标识符,这种标识符适用于您的情况,但我建议您添加一个真正的唯一标识符。就像在对象列表中添加字段ID。

以下是经过更正的代码段:

var svg = d3.select('body').append('svg')
    .attr('width', 250)
    .attr('height', 250)
    .append('g');

//render the data
function render(datum) {
    //Bind 
    var groups = svg.selectAll("g").data(datum, d => (d.x)/(d.y));
    var groupEnter = groups.enter().append('g');

    var circles = 		     groupEnter.append("circle").attr('r', 10)
        .attr('cx', function(d) {
            return d.x;
        })
        .attr('cy', function(d) {
            return d.y;
        });

    groups.exit().remove();
}

var myObjects = [{ x: 100, y: 100 }, { x: 130, y: 120 }, { x: 80, y: 180},{ x: 180, y: 80 }, { x: 180, y: 40 }];
var newObjects = [{ x: 200, y: 120 }, { x: 150, y: 160 }, { x: 20, y: 80}, { x: 80, y: 60 }, { x: 100, y: 20 }];

function removeEls() {
    svg.selectAll('circle').remove();
}

render(myObjects);
svg {
    width: 500px;
    height: 500px
}

button {
    float: left
}

text {
    text-anchor: middle;
}

circle {
    fill: orange;
    stroke: orange;
    fill-opacity: 0.5;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<button onclick="render(newObjects)">Update</button>
<button onclick="render(myObjects);">Render</button>
<button onclick="removeEls();">removeEls</button>