2015-03-11 2 views
0

В книге «Визуализация данных с помощью кулинарной книги D3» (глава 8) появляется пример, где автор рисует две строки. В основном, данные создаются случайным образом:Обновление данных в простой многоразовой диаграмме D3

var numberOfSeries = 2, 
    numberOfDataPoint = 11, 
    data = []; 

for (var i = 0; i < numberOfSeries; ++i) 
    data.push(d3.range(numberOfDataPoint).map(function (i) { 
     return {x: i, y: randomData()}; 
    })); 

Затем автор создает экземпляр диаграммы и определяет область Шкалы:

var chart = lineChart() 
     .x(d3.scale.linear().domain([0, 10])) 
     .y(d3.scale.linear().domain([0, 10])); 

После этого, данные вводят с помощью метода :

data.forEach(function (series) { 
    chart.addSeries(series); 
}); 

И, наконец, диаграмма оказывается вызовом render() метод:

chart.render(); 

Кроме того, участок имеет Update днище, что позволяет обновлять данные показали, вызвав эту функцию:

function update() { 
    for (var i = 0; i < data.length; ++i) { 
     var series = data[i]; 
     series.length = 0; 
     for (var j = 0; j < numberOfDataPoint; ++j) 
      series.push({x: j, y: randomData()}); 
    } 

    chart.render(); 
} 

Моя проблема заключается в том, что я не могу понять, как эти данные обновляются в сюжете без вызова метода снова, после нажатия кнопки Update, то есть в функции update(). Внутренние данные хранятся в переменной _data, которая может быть изменена с помощью метода . Есть идеи?

Большое спасибо!

Полный код here, но после я скопировал самые важные части:

function lineChart() { // <-1A 
    var _chart = {}; 

    var _width = 600, _height = 300, // <-1B 
      _margins = {top: 30, left: 30, right: 30, bottom: 30}, 
      _x, _y, 
      _data = [], 
      _colors = d3.scale.category10(), 
      _svg, 
      _bodyG, 
      _line; 

    _chart.render = function() { // <-2A 
     if (!_svg) { 
      _svg = d3.select("body").append("svg") // <-2B 
        .attr("height", _height) 
        .attr("width", _width); 

      renderAxes(_svg); 

      defineBodyClip(_svg); 
     } 

     renderBody(_svg); 
    }; 

    // Axis rendering functions ... 


    function renderBody(svg) { // <-2D 
     if (!_bodyG) 
      _bodyG = svg.append("g") 
        .attr("class", "body") 
        .attr("transform", "translate(" 
         + xStart() + "," 
         + yEnd() + ")") // <-2E 
        .attr("clip-path", "url(#body-clip)");   

     renderLines(); 

    } 

    function renderLines() { 
     _line = d3.svg.line() //<-4A 
         .x(function (d) { return _x(d.x); }) 
         .y(function (d) { return _y(d.y); }); 

     _bodyG.selectAll("path.line") 
        .data(_data) 
       .enter() //<-4B 
       .append("path")     
       .style("stroke", function (d, i) { 
        return _colors(i); //<-4C 
       }) 
       .attr("class", "line"); 

     _bodyG.selectAll("path.line") 
       .data(_data) 
       .transition() //<-4D 
       .attr("d", function (d) { return _line(d); }); 
    } 

    //Some getter/setters functions and other stuff 

    _chart.addSeries = function (series) { // <-1D 
     _data.push(series); 
     return _chart; 
    }; 

    return _chart; // <-1E 
} 

function randomData() { 
    return Math.random() * 9; 
} 

function update() { 
    for (var i = 0; i < data.length; ++i) { 
     var series = data[i]; 
     series.length = 0; 
     for (var j = 0; j < numberOfDataPoint; ++j) 
      series.push({x: j, y: randomData()}); 
    } 

    chart.render(); 
} 

var numberOfSeries = 2, 
    numberOfDataPoint = 11, 
    data = []; 

for (var i = 0; i < numberOfSeries; ++i) 
    data.push(d3.range(numberOfDataPoint).map(function (i) { 
     return {x: i, y: randomData()}; 
    })); 

var chart = lineChart() 
     .x(d3.scale.linear().domain([0, 10])) 
     .y(d3.scale.linear().domain([0, 10])); 

data.forEach(function (series) { 
    chart.addSeries(series); 
}); 

chart.render(); 

ответ

1

update() функция модифицирует каждую серию в месте, которое подобран автоматически с помощью функции render(). Это работает, потому что замыкание хранит ссылку в серию (которая изменена), а не фактические значения.

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

При этом я бы не счел, что код особенно хорошо разработан.

+0

Спасибо за быстрый ответ. Кстати, можете ли вы порекомендовать мне какую-нибудь книгу/учебник для чего-то большего, что «начиная с D3»? Некоторые ссылки с хорошей практикой и дизайном? –

+2

Я не читал его сам, но я считаю, что [книга Скотта Мюррея] (http://alignedleft.com/work/d3-book) неплоха. –

Смежные вопросы