Update bar chart in d3 based on user input

时间:2017-12-06 15:58:16

标签: javascript d3.js svg

I'm trying to update the bar chart in d3 based on the input selected by the user. The updated data is being displayed but it is being displayed on the old SVG elements. I tried using exit().remove() but it did not work. Can anyone edit the code attached below so that the old SVG elements are removed.

    <html>
<head>
<script src="https://d3js.org/d3.v4.min.js" charset="utf-8"></script>
<style>
.rect {
  fill: steelblue;
}

.text {
  fill: white;
  font: 10px sans-serif;
  text-anchor: middle;
}
</style>
</head>
<body>
<select id = "variable">
                    <option >select</option>
                    <option value="AZ">Arizona</option>
                    <option value="IL">Illinois</option>
                    <option value="NV">NV</option>          
</select>
<script>
var margin = {top: 20, right: 20, bottom: 70, left: 40},
        width = 500 - margin.left - margin.right,
        height = 400 - margin.top - margin.bottom;
var y = d3.scaleLinear()
        .domain([0,5])
        .range([height, 0]);
var yAxis = d3.axisLeft(y)
                .ticks(10);
var svg = d3.select("body")
            .append("svg")
            .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.top + margin.bottom)
            .append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var bar;

function update(state)
{
d3.csv("test3.csv", function(error, data) 
    {
            data = data.filter(function(d, i) 
                                { 
                                    if (d['b_state'] == state) 
                                    {
                                    return d;
                                    }
                                });
            data = data.filter(function(d, i) 
                                { 
                                    if (i<10) 
                                    {
                                    return d;
                                    }
                                });

            var barWidth = width / data.length;

            svg.append("g")
                 .attr("class", "y axis")
                 .call(yAxis)
                 .append("text")
                 .attr("transform", "rotate(-90)")
                 .attr("y", 6)
                 .attr("dy", ".71em")
                 .style("text-anchor", "end")
                 .text("Stars");

                bar = svg.selectAll("bar")
                          .data(data)
                          .enter()
                          .append("g")
                          .attr("transform", function(d, i) { return "translate(" + i * barWidth + ",0)"; });


                bar.append("rect")
                   .attr("y", function(d) { return y(d.b_stars); })
                   .attr("height", function(d) { return height - y(d.b_stars); })
                   .attr("width", barWidth - 1)
                   .attr("fill", "steelblue");

                bar.append("text")
                      .attr("x", function(d) { return height - y(d.b_stars); })
                      .attr("y", -40)
                      .attr("dy", ".75em")
                      .text(function(d) { return d.b_name; })
                      .attr("transform", "rotate(90)" );
});
svg.exit().remove();
bar.exit().remove();
}
d3.select("#variable")// selects the variable
  .on("change", function() {// function that is called on changing
    var variableName = document.getElementById("variable").value;// reads the variable value selected into another variable
    update(variableName);});
</script>
</body>

1 个答案:

答案 0 :(得分:0)

此处的问题与您的bar选择有关。您可以查看d3文档的这一部分:Joining data

写作

bar = svg.selectAll("bar")
    .data(data)
    .enter()

您正在选择所有bar个元素,并加入data,并且使用此enter(),您获得的所有data项都未与{{1}相关联元素(enter() documentation)。 但是,您的bar选择器不匹配任何内容。 bar / select()的参数必须是选择器(元素,类selectAll(),id . ...)。这就是为什么#你的enter()选择总是创建新元素而不是更新它们。

因此,第一步是重写此选择并创建稍后将与此选择匹配的DOM元素:

enter()

在这里,我们选择bar = svg.selectAll(".bar") .data(data) .enter() .append("g") .attr('class', 'bar') .attr("transform", function(d, i) { return "translate(" + i * barWidth + ",0)"; }); 类的所有元素。如果没有DOM元素链接到bar中的项目,那么我们将创建它(在enter()选择中),作为具有data类的新g

如果选择的方式如此,则在下次更新时,bar将匹配之前创建的所有selectAll('.bar'),而不会对现有元素应用g选项。< / p>

要更新或删除现有的栏,您可以编写如下代码:

enter()