Как обновить диаграмму d3.js с новыми данными

Ive начал с примера "Давайте сделаем гистограмму" здесь: http://bost.ocks.org/mike/bar/

И мне трудно понять, как сделать очень простую гистограмму, сделанную с обновлением элементов HTML5 новыми данными. Вот мой код:

<!DOCTYPE html>
<html>
  <head>
    <style>
      #work_queues_chart div {
        font-size: 0.5em;
        font-family: sans-serif;

        color: white;
        background-color: steelblue;

        text-align: right;
        padding: 0.5em;
        margin: 0.2em;
      }
    </style>
    <script src="http://d3js.org/d3.v3.min.js" charset="utf-8" />
    <script type="text/javascript">

      function init() {

        var data = [0, 0, 0, 0, 0, 0];

        /* scale is a function that normalizes a value in data into the range 0-98 */
        var scale = d3.scale.linear()
                      .domain([0, 200])
                      .range([0, 98]);

        var bars = d3.select("#work_queues_chart")
                     .selectAll("div")
                       .data(data)
                     .enter().append("div");

        bars.style("width", function(d) { return scale(d) + "%"; })
        bars.text(function(d) { return d; });

      }

      function update() {

        var data = [4, 8, 15, 16, 23, 42];

        /* http://stackoverflow.com/info/14958825/dynamically-update-chart-data-in-d3 */
      }

      window.onload = init;

    </script>

  </head>
  <body>
    <div id="work_queues_chart" />
    <button onclick="update()">Update</button>
  </body>
</html>

Вопрос в том, что я помещаю в update(), чтобы заставить бары рисовать новыми данными? Я попробовал d3.select("#work_queues_chart").selectAll("div").data(data) с новыми данными, но Im неясно, что должно произойти дальше (или это был правильный ход).

Ответ 1

Принятый ответ был дан до того, как была выпущена версия d3 версии 4, но если вы используете d3v4, вам нужно сделать другой вариант из-за (выдержка из changelog):

selection.append больше не объединяет ввод узлов в обновление отбор; используйте selection.merge, чтобы объединить ввод и обновление после соединение данных.

// enter and update selection
bars
  .enter()
  .append("div")
  .merge(bars) // <== !!!
  .style("width", function (d) {return scale(d) + "%";})
  .text(function (d) {return d;});


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

Рабочий пример в скрытом фрагменте ниже:

function draw(data) {
    var scale = d3.scaleLinear()
        .domain([0, 50])
        .range([0, 100]);

    var bars = d3.select("#work_queues_chart")
        .selectAll("div")
        .attr("id","work_queues_chart")
        .data(data);
     
    // enter and update selection
    bars
      .enter().append("div")
      .merge(bars)
      .style("width", function (d) {return scale(d) + "%";})
      .text(function (d) {return d;});

    
    // exit selection
    bars
        .exit().remove();
};

function update() {
    var data = [4, 8, 15, 16, 23, 42];
    draw(data);
};

var data = [10, 10, 10, 10, 10, 10];
window.onload = draw(data);

d3.select('#update')
    .on("click",update);
#work_queues_chart div {
    font-size: 0.5em;
    font-family: sans-serif;
    color: white;
    background-color: steelblue;
    text-align: right;
    padding: 0.5em;
    margin: 0.2em;
}
<div id="work_queues_chart" />
<button id="update">Update</button>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.11.0/d3.min.js"></script>

Ответ 2

Я создал для вас скрипку здесь. Это простой пример того, что у вас было с несколькими изменениями, в частности, разделение параметров ввода, обновления и выхода. Это поможет вам понять процесс обновления в D3.

// enter selection
bars
    .enter().append("div");

// update selection
bars
    .style("width", function (d) {return scale(d) + "%";})
    .text(function (d) {return d;});

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