正在删除的SVG组不正确

Incorrect SVG group being deleted

本文关键字:不正确 SVG 删除      更新时间:2023-09-26

我想删除被点击的栏,但由于某种原因,它总是删除最后一个栏。我想答案可能在下面的文章中(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>

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

主要问题是,在drawChart函数开始时,您没有删除所有旧的条形图。我添加了这个:

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

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

// 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();,因为它没有什么区别之后,我意识到让我的答案更加地道的重要性。因此,我创建了一个更新的fiddle,它利用了exit选择,并消除了手动删除DOM元素的需要。

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

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

更新了FIDDLE