正在删除的SVG组不正确

时间:2014-10-11 03:10:22

标签: javascript svg d3.js

我想删除单击的栏,但由于某种原因,它总是删除最后一个栏。我认为答案可能在下面的文章(http://pothibo.com/2013/09/d3-js-how-to-handle-dynamic-json-data/)中,但我不确定是否有必要手动为每个元素分配一个键。我花了好几个小时试图让它发挥作用,所以我希望有人可以指出我正确的方向。提前谢谢。

<html>
<head>
    <title>Interactive Div-based Bar Chart</title>
    <style type="text/css">
    .chart rect {
        fill: teal;
    }
    .chart text {
        fill: white;
        font: 30px sans-serif;
        text-anchor: end;
    }
    </style>
    <script src="Scripts/d3.min.js"></script>
</head>
<body>
    <div id="data-field"></div>
    <button id="add-btn">Add Data</button>
    <p>Click on a bar to remove it</p>

    <script>
        var barHeight = 75, margin = 3, padding = 3;

        var chartData = [6,12,15,21,29,41];

        var chart = d3.select("body").append("svg").attr("class","chart");

        drawChart();

        function drawChart() {

            var selection = chart.selectAll("g")
                .data(chartData);

            // Remove extra bars
            selection.exit()
                .remove();

            // Add more bars
            var groups = selection.enter()
                .append("g");

            var bars = groups
                .append("rect");

            var labels = groups
                .append("text");

            // Update existing bars
            groups
                .attr("transform", function (d, i) { return "translate(0," + i * (barHeight + margin) + ")"; })
                .on("click", function (d, i) { chartData.splice(i, 1); drawChart(); });      

            bars
                .attr("width", function (d) { return d * 10 + "px"; })
                .attr("height", barHeight);     

            labels
                .attr("x", function (d) { return d * 10 - padding + "px"; })
                .attr("y", barHeight / 3 + padding + "px")
                .text(function (d) { return d; });

            // update list of numbers
            d3.select("#data-field").text("numbers: [" + chartData.join(", ") + "]");
        }

        // add more data
        d3.select("#add-btn")
            .on("click", function(d) { chartData.push(Math.round(Math.random() * 100)); drawChart(); });

    </script>

</body>
</html>

2 个答案:

答案 0 :(得分:2)

在此处查看我的解决方案:http://fiddle.jshell.net/sydvpsfp/

主要问题是你没有在drawChart函数开头删除所有旧条。 我添加了这个:

        // remove any old bars
        var oldBars=chart.selectAll("g");
        if (oldBars.size()>0)
            oldBars.remove();

答案 1 :(得分:1)

以下是您需要进行的更改,并附有评论:

// Update existing bars; do not use groups here since it represents
// only the ENTER selection, and not ALL g elements
selection
    .attr("transform", function (d, i) { return "translate(0," + i * (barHeight + margin) + ")"; })
    .on("click", function (d, i) { 
        d3.select(this).remove(); // remove appropriate DOM element
        chartData.splice(i, 1); 
        drawChart(); 
    });

这是FIDDLE

重要编辑:

@loucatsfan问我为什么不简单地摆脱selection.exit().remove();,因为它没有任何区别,我意识到让我的答案更加惯用的重要性。因此,我创建了一个利用exit选择的更新小提琴,并且无需手动删除DOM元素。

此外,同样重要的是,处理分组与非分组元素的更新之间存在一些细微差别(使用selectselectAll)。因此,我修改了代码以更适当地处理分组元素。

您可以找到有关正确处理分组元素herehere的更多信息。但这是承诺的改进:

<强> UPDATED FIDDLE