d3.js如何使用单选按钮结果更新图表

时间:2018-04-03 15:11:10

标签: javascript d3.js radio-button

我已经阅读过关于如何从单选按钮返回值的多个SO答案,但我对如何使用此返回值更新图表感到有些困惑。

在下面的示例中,单选按钮不会更新任何内容,这里出了什么问题?

<!DOCTYPE html>
<html lang="en">
    <head>
      <script src="https://d3js.org/d3.v4.min.js"></script>
        <meta charset="utf-8">
        <title>D3: Loading data from a CSV file</title>
  </head>
    <body>
        <div class="chart-container">
    <form class="controls">
        Scale:
         <label>
          <label><input type="radio" name="market" value="A" checked> 
            A</label>
                <label><input type="radio" name="market" value="B"> B</label> 
      </label>
    </form>
    <svg class="chart js-chart"></svg>
</div>

        <script type="text/javascript">

      var margin = {top: 20, right: 20, bottom: 30, left: 40},
            w = 600 - margin.left - margin.right,
            h = 300 - margin.top - margin.bottom;


      d3.csv('food.csv', function(error, data) {
        if (error) throw error;

        // format the data
        data.forEach(function(d) {
          d.Deliciousness=+d.Deliciousness
        });

                //radio button
      d3.selectAll(("input[name='market']")).on("change", function(){
      console.log(this.value)
      var data_new=data.filter(d=>(d.Market==this.value));   
            console.log(data_new);
        redraw(data_new);
        }); 
    function redraw(data){  
      var svg = d3.select("body")
                        .append("svg")
                        .attr("width", w + margin.left + margin.right)
                        .attr("height", h + margin.top + margin.bottom)
                .append("g")
                .attr("transform", "translate(" + margin.left+"," +
                 margin.top+")");

      var xScale = d3.scaleBand()
        .domain(d=>d.Food)
        .range([0,w])
        .paddingInner(0.2);
     xScale.domain(data.map(function(d) { return d.Food; }));


      var xAxis = d3.axisBottom()
        .scale(xScale)
        .ticks(5);

      var yScale = d3.scaleLinear()
        .domain([0, d3.max(data, d=>d.Deliciousness)])
        .rangeRound([h,0]);

      var yAxis = d3.axisLeft()
        .scale(yScale)
        .ticks(5);

      svg.selectAll('rect')
        .data(data)
        .enter()
        .append('rect')
        .attr('x',(d,i) => margin.left + i*w/data.length)
        .attr('y',d=>yScale(d.Deliciousness))
        .attr('width', 20)
        .attr('height',d =>h-yScale(d.Deliciousness))
        .attr('fill',"blue");






      }
        })
       // });
        </script>
    </body>
</html>

,数据是:

Market, Food,Deliciousness
A, Apples,9
A, Green Beans,5
A, Bananas,5
B, Apples,4
B, Green Beans,8
B, Bananas,7

它只返回B市场的图表,选择A市场并不起作用:最初只是空白。

然后在选择B后,B图表显示,切换回A,B图表保留,A图表不显示。

enter image description here这里有什么遗漏?提前谢谢。

1 个答案:

答案 0 :(得分:1)

代码中的主要问题是:

  1. 您正在redraw()内附加SVG。将其移到外面,仅附加一次的SVG。
  2. 您没有更新并输入选择。它应该是:

    var rect = svg.selectAll('rect')
        .data(data);
    
    var rectEnter = rect.enter()
        .append('rect')
        .merge(rect)
        .attr('x', (d) => xScale(d.Food))
        .attr('y', d => yScale(d.Deliciousness))
        .attr('width', xScale.bandwidth())
        .attr('height', d => h - yScale(d.Deliciousness))
        .attr('fill', "blue");
    
  3. 此外,退出选择也是一个好主意。

    小问题:

    1. 每次单击单选按钮时都不要定义刻度。只需更改他们的域名。
    2. 你这里有一个乐队。因此,请将其用于xwidth属性。
    3. 您的CSV有空格。删除它们。
    4. 这是更新的bl.ocks:https://bl.ocks.org/GerardoFurtado/40c4a36d48e6dfaa30f0325f2973098f/fd2f8c76bf3cbaf6b57c34dfc2f00b0d394079ac