D3: Как я могу изменить данные в существующей гистограмме

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

Вот мой код:

var data = [23, 85, 67, 38, 70]; //dummy, normally much more
labellist = ['label1','label2','label3','label4','label5'];

var w = 815,
    h = 500,
    labelpad = 165,
    x = d3.scale.linear().domain([0, 100]).range([0, w]),
    y = d3.scale.ordinal().domain(d3.range(data.length)).rangeBands([0, h], .2);

mySvg = d3.select("#chart")
  .append("svg");

vis = mySvg.attr("width", w + 40)
    .attr("height", h + 20)
    .append("svg:g")
    .attr("transform", "translate(20,0)");

bars = vis.selectAll("g.bar")
    .data(data)
    .enter().append("svg:g")
    .attr("class", "bar")
    .attr("transform", function(d, i) { return "translate(" + labelpad + "," + y(i) + ")"; })


bars.append("svg:rect")

    .transition()
    .duration(500)
    .attr("width", x)
    .attr("height", y.rangeBand())
    ;



var rules = vis.selectAll("g.rule")
    .data(x.ticks(10))
  .enter().append("svg:g")
    .attr("class", "rule")
    .attr("transform", function(d) { return "translate(" + x(d) + ", 0)"; });

rules.append("svg:line")
    .attr("y1", h)
    .attr("y2", h + 6)
    .attr("x1", labelpad)
    .attr("x2", labelpad)
    .attr("stroke", "black");
rules.append("svg:line")
    .attr("y1", 0)
    .attr("y2", h)
    .attr("x1", labelpad)
    .attr("x2", labelpad)
    .attr("stroke", "white")
    .attr("stroke-opacity", .3);

Как я могу программно изменить данные, чтобы добавить и удалить другие полосы и позволить существующим скользить вверх/вниз?


person Hokascha    schedule 28.08.2012    source источник


Ответы (1)


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

Что касается переходов, вы хотите изменить свой код примерно так:

bars = vis.selectAll("g.bar")
    .data(data);

bars.enter().append("svg:g")
    .attr("class", "bar")
    .append("svg:rect").

bars.transition().duration(500)
    .attr("transform", function(d, i) { 
         return "translate(" + labelpad + "," + y(i) + ")"; 
     })
    .selectAll("svg:rect")
    .attr("width", x)
    .attr("height", y.rangeBand())
;

bars.exit().transition().duration(500)
    .selectAll("svg:rect")
    .attr("height", 0)
    .remove();

Функцию "enter()" лучше всего использовать для немедленного создания структуры. Затем используйте начальный объект выбора (столбцы), чтобы применить новые данные ко всем элементам.

Вы также, вероятно, захотите удалить все устаревшие бары. Здесь я изменил их размер до 0, а затем удалил, но вы можете повозиться с ним, чтобы получить желаемый эффект.

person Glenn    schedule 28.08.2012
comment
Спасибо за ваш ответ, я новичок в d3 - знаете ли вы какой-либо учебник или пример, показывающий использование упомянутых вами ключей? Как будет выглядеть моя функция updateChart()? Когда я пробую ваш код для переходов, диаграмма не отображается, я получаю Uncaught Error: SYNTAX_ERR: DOM Exception 12 в d3.v2.js в d3_selection(groups) (я уже исправил вашу опечатку во втором вызове, точка вместо точки с запятой ) - person Hokascha; 29.08.2012
comment
Я не запускал этот код, поэтому, вероятно, с ним связаны другие проблемы. Я просто пытался показать вам идею использования функций входа/выхода для добавления/удаления элементов. - person Glenn; 30.08.2012
comment
Это хороший вариант с гистограммами, показывающий, как красиво добавлять гистограммы: mbostock. github.com/d3/tutorial/bar-2.html - person Glenn; 30.08.2012