Изменение данных с помощью интерактивного раскрывающегося списка для ввода фильтра в d3.js

#javascript #d3.js

Вопрос:

Я думал, что это должно быть просто, но у меня возникли проблемы. Я пытаюсь отфильтровать набор данных на основе переменной, выбранной в раскрывающемся списке, и обновить диаграмму в d3. Раскрывающийся список заполняется, и начальная диаграмма отображается нормально, но не обновляется, когда я изменяю раскрывающийся список.

Примеры данных:

 Year,VarA,VarB,VarC,VarD
1984,34,56,90,X
1984,69,38,58,Y
1988,50,35,28,X

 

Соответствующий код:

 // Create a dropdown
    var yearMenu = d3.select("#yearDropdown")

    yearMenu
    .append("select")
    .selectAll("option")
        .data(nest)
        .enter()
        .append("option")
        .attr("value", ([key, ]) => key)
        .text(([key, ]) => key)

// Circles
  var circles = svg.selectAll('circle')
      .data(data.filter(d => d.Year == "1984"))
      .enter()
      .append('circle')
      .attr('cx', d => xScale(d.VarA))
      .attr('cy', d => yScale(d.VarB))
      .attr('r', d => rScale(d.VarC)/rDivisor)
      .attr('stroke', 'black')
      .attr('stroke-width',2)
      .style('fill', 'white')
      .attr('class', 'points')


var updateGraph = function(selectedYear) {

  var dataFilter = data.filter(d => d.Year == selectedYear)

    circles.data(dataFilter)
          .selectAll("circle.points")
          .transition()
          .duration(1000)
          .attr('cx', d => xScale(d.VarA))
          .attr('cy', d => yScale(d.VarB))
          .attr('r', d => rScale(d.VarC)/rDivisor)
      }

// When the button is changed, run the updateChart function
    yearMenu.on("change", function() {
        // recover the option that has been chosen
        var selectedOption = d3.select(this)
        .select("select")
        .property("value")
        // run the updateChart function with this selected option
        updateGraph(selectedOption)

    });
 

Ответ №1:

Вот пример:

 <!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <script src="https://d3js.org/d3.v7.js"></script>
</head>

<body>
    <div id="yearDropdown"></div>
    <div id="chart"></div>

    <script>
      // set up

      const width = 200;
      const height = 200;

      const svg = d3.select('#chart')
        .append('svg')
          .attr('width', width)
          .attr('height', height);

      // data

      const data = [
        { Year: '1984', VarA: 34, VarB: 56, VarC: 90, VarD: 'X' },
        { Year: '1984', VarA: 69, VarB: 38, VarC: 58, VarD: 'Y' },
        { Year: '1988', VarA: 50, VarB: 35, VarC: 28, VarD: 'X' }
      ];

      // scales

      const xScale = d3.scaleLinear()
          .domain([0, 100])
          .range([0, width]);

      const yScale = d3.scaleLinear()
          .domain([0, 100])
          .range([height, 0]);

      const rScale = d3.scaleLinear()
          .domain([0, 100])
          .range([0, 20]);

      // circles

      let circles = svg.selectAll('circle');

      function drawCircles(year) {
        circles = circles
          .data(data.filter(d => d.Year === year))
          .join('circle')
            .attr('stroke', 'black')
            .attr('stroke-width', 2)
            .style('fill', 'white');

        circles
          .transition()
          .duration(1000)
            .attr('cx', d => xScale(d.VarA))
            .attr('cy', d => yScale(d.VarB))
            .attr('r', d => rScale(d.VarC));
      }

      // select menu

      const yearMenu = d3.select('#yearDropdown')
        .append('select');

      yearMenu.selectAll('option')
        .data(['1984', '1988'])
        .join('option')
          .attr('value', d => d)
          .text(d => d);

      yearMenu.on('change', function(event) {
        drawCircles(event.target.value);
      });

      // draw the inital circles
      drawCircles(yearMenu.property('value'));
    </script>
</body>
</html> 

yearMenu должно быть меню выбора, а не div, содержащий его. Кроме того, функция, которая обновляет диаграмму, должна обрабатывать, когда новые данные содержат другое количество элементов, чем предыдущие данные.