2017-02-13 3 views
1

У меня есть гистограмма, которая отлично работает, за исключением случаев, когда ей передается обновление с более длинными данными в функции updateChart. Новые бары не создаются, хотя существующие бары делают переход правильно.d3.js (v3) enter() не работает в обновлении гистограммы

jsFiddle

var initialData = [ 
    {Date: '2017-01-01', Volume: 56}, 
    {Date: '2017-01-02', Volume: 98}, 
    {Date: '2017-01-03', Volume: 45}, 
    {Date: '2017-01-04', Volume: 21}, 
    {Date: '2017-01-05', Volume: 40} 
    ]; 
    var updatedData = [ 
    {Date: '2016-12-27', Volume: 89}, 
    {Date: '2016-12-28', Volume: 81}, 
    {Date: '2016-12-29', Volume: 75}, 
    {Date: '2016-12-30', Volume: 160}, 
    {Date: '2016-12-31', Volume: 65}, 
    {Date: '2017-01-01', Volume: 56}, 
    {Date: '2017-01-02', Volume: 98}, 
    {Date: '2017-01-03', Volume: 120}, 
    {Date: '2017-01-04', Volume: 21}, 
    {Date: '2017-01-05', Volume: 40} 
]; 


var bottomPadding = 20; 
var leftPadding = 30; 
var topPadding = 0; 
var rightPadding = 40; 
var width = 375 - leftPadding-rightPadding; 
var height = width * .75; 
var xScale,volScale; 
var xAxis,volAxis,volAxisGroup; 

drawChart(); 

function drawChart() { 

    var gData = initialData; 

    var minDate = getDate(gData[0]); 
    var maxDate = getDate(gData[gData.length - 1]); 
    var maxVol = d3.max(gData, function (d) { return +d.Volume }); 

    xScale = d3.time.scale() 
    .range([leftPadding, width + leftPadding]); 

    volScale = d3.scale.linear() 
    .rangeRound([height, (topPadding+10)]); 

    //set up canvas 
    var stockLineCht = d3.select("#chart") 
    .append("svg:svg") 
    .attr("width", width + leftPadding + rightPadding) 
    .attr("height", height + bottomPadding + topPadding); 

    //add x-axis 
    xAxis = d3.svg.axis() 
    .scale(xScale) 
    .orient("bottom") 
    .ticks(5); 

    //add r-axis 
    volAxis = d3.svg.axis() 
    .scale(volScale) 
    .orient("right") 
    .tickFormat(d3.format("s")) 
    .ticks(5); 

    volAxisGroup = stockLineCht.append("g") 
    .attr("class", "axis") 
    .attr("transform", "translate(" + (leftPadding + width) + ",0)"); 

    xScale.domain([minDate, maxDate]); 
    volScale.domain([0, maxVol]); 

    //VOLUME bars 
    var y1Bars = stockLineCht.selectAll("bars") 
    .data(gData) 
    .enter() 
    .append("svg:rect") 
    .attr("class", "bar"); 

    y1Bars.attr("x", function (d) { return xScale(getDate(d)) - (width/(gData.length * 1.5)) ; }) 
    .attr("y", function (d) { return volScale(d.Volume); }) 
    .attr("height", function (d) { return height - volScale(d.Volume); }) 
    .attr("width", function (d) {return width/(gData.length * 1.5);}); 

    volAxisGroup 
    .attr("class", "r axis") 
    .call(volAxis); 

    stockLineCht.append("g") 
    .attr("class", "x axis") 
    .attr("transform", "translate(0," + height + ")") 
    .call(xAxis); 
} 

window.updateChart = function() { 
    console.log('update called'); 
    var newData = updatedData; 
    console.log(newData); 

    var minDate = getDate(newData[0]); 
    var maxDate = getDate(newData[newData.length - 1]); 
    var maxVol = d3.max(newData, function (d) { return +d.Volume }); 

    xScale.domain([minDate, maxDate]); 
    volScale.domain([0, maxVol]); 

    var stockLineCht = d3.select("#chart"); 

    var y1Bars = stockLineCht.selectAll(".bar") 
    .data(newData); 

    y1Bars.enter() 
    //.append("g") 
    .append("svg:rect") 
    .attr("class", "bar"); 
    //.append("svg:rect"); 

    y1Bars.transition() 
    .duration(750) 
    .attr("x", function (d) { return xScale(getDate(d)) - (width/(newData.length * 1.5)) ; }) 
    .attr("y", function (d) { return volScale(d.Volume); }) 
    .attr("height", function (d) { return height - volScale(d.Volume); }) 
    .attr("width", function (d) { return width/(newData.length * 1.5); }); 

    y1Bars.exit().transition().duration(750) 
     .selectAll("rect") 
     .attr("height", 0) 
     .remove(); 

    stockLineCht.select(".x.axis") // change the x axis 
    .transition() 
    .duration(750) 
    .call(xAxis); 

    stockLineCht.select(".r.axis") // change the r axis 
    .transition() 
    .duration(750) 
    .call(volAxis); 
} 

    // helper function 
    function getDate(d) { 
    return new Date(d.Date); 
    } 
+0

хмм, это выглядит, как вы воссоздавая диаграмму в функции обновления. Это может помочь [Обновить данные d3.js с нажатием кнопки] (http://bl.ocks.org/d3noob/7030f35b72de721622b8) – theWhiteFox

+0

Я не думаю, что я воссоздаю это - в скрипке бары переходят на новые данные - это просто, что новые бары не «вводятся» для учета дополнительных точек данных. –

+0

Похоже, что ваша функция обновления в значительной степени похожа на вашу функцию рисования, за исключением различий, как в функции draw 'xScale = d3. time.scale(). range ([leftPadding, width + leftPadding]); 'и в вашей функции обновления у вас есть' xScale.domain ([minDate, maxDate]); ' – theWhiteFox

ответ

1

Это выглядит как рабочий раствор. Я изменил несколько вещей.

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

var y1Bars = d3.select("svg").selectAll(".bar") 
    .data(newData); 

Я также изменил ту часть, где вы вводите бары так это больше похоже на transition-

y1Bars.enter() 
    //.append("g") 
    .append("rect") 
    .attr("class", "bar") 
    .attr("x", width) 
    .attr("y", function(d) { 
     return height - volScale(d.Volume); 
    }) 
    .attr("width", (width/(newData.length * 1.5))) 
    .attr("height", function(d) { 
     return volScale(d.Volume); 
    }); 

Решение здесь - https://jsfiddle.net/w7eaf3o5/6/

+0

Спасибо, что это работает. Я вижу, что селектор, который я использовал для баров, отключен и что я не обновлял attrs выбора ввода. –