D3 - 每2秒更新一次条形图

时间:2016-01-18 09:02:57

标签: javascript d3.js charts

我有一个D3条形图,最初绘制了一些数据。我将每2秒获得一次新数据。此新数据可能是新项目或现有项目的新计数。我想相应地更新图表。

这就是我的尝试:

https://jsfiddle.net/rutwick/an1d95h1/2/

var sales = [
    { product: 'Hoodie',  count: 7 },
    { product: 'Jacket',  count: 6 },
    { product: 'Snuggie', count: 9 },
    { product: 'Beanie', count: 8 }
];
var startTimer = false;

function drawGraph() {

    //select the svg
    var svg = d3.select('svg');

    //Select all the rect elements and assign the data to them
    var rects = svg.selectAll('rect')
    .data(sales);

    //This will access the rect element for creating new rect elements
    var newRects = rects.enter();

    // recall that scales are functions that map from
    // data space to screen space
    // Max limit for Y axis
    var maxCount = d3.max(sales, function(d, i) {
        return d.count;
    });

    //X axis will have bars, hence ordinal scale used
    //domain - data - Product values
    //Rangebound specifies max limit and the padding around the bands
    var x = d3.scale.ordinal()
    .domain(sales.map(function(d) {
        return d.product;
    }))
    .rangeRoundBands([0, 500], 0.10); //300 = Total width of all bars, 0.10 = Factor of space between the bars

    //Y axis is linear, hence linear scale used
    var y = d3.scale.linear()
        .range([400, 0])
        .domain([0, maxCount]);

    newRects.append('rect')
        .attr('x', function(d) {
            return x(d.product);
        })
    .attr('y', function(d, i) {
        return y(d.count);
    })
    .attr('width', x.rangeBand())
    .attr('height', function(d, i) {
      return 400 - y(d.count);
    });

    startTimer = true;
    rects.exit().remove();
}

function updateGraph(){
    if(!startTimer) {
        return;
    }
    var rand = Math.floor(Math.random() * sales.length);
    /*if(sales[rand].count % 2 === 0) {
    sales[rand].count += 2;
        console.log(sales[rand].count);
    }*/
    sales.push({ product: 'Denim', count: 1 });
    sales.push({ product: 'Sweatshirt', count: 12 });
    drawGraph();
}
setInterval(updateGraph, 2000);
drawGraph();

它会更新,但不会重绘图表。只需在旧的栏上添加新栏。我目前的计划包括使用jQuery删除所有rect元素,但我不知道它是否可行。

在x轴和y轴上更新整个图表究竟需要做些什么?

2 个答案:

答案 0 :(得分:2)

你可以这样做:

首先,你需要像这样定义对象:

var rects = svg.selectAll('rect')
.data(sales, function(d){/*Unique ID of a record*/ return d.product;});

现在创建这样的矩形:

  newRects.append('rect');

现在用新的宽度和高度更新所有的矩形。

  //do update
  d3.selectAll("rect")
  .attr('class', "rects")
  .attr('x', function(d) {
    console.log(d)
    return x(d.product);
    })
  .attr('y', function(d, i) {
    return y(d.count);
  })
  .attr('width', x.rangeBand())
  .attr('height', function(d, i) {
    return 400 - y(d.count);
  });

最后删除已删除数据的栏:

  //remove not there
    rects.exit().remove()

您的代码未更新的问题:

执行此操作时,属性仅在create

上更新
newRects.append('rect')
        .attr('x', function(d) {
            return x(d.product);
        })
    .attr('y', function(d, i) {
        return y(d.count);
    })
    .attr('width', x.rangeBand())
    .attr('height', function(d, i) {
      return 400 - y(d.count);
    });

工作代码here

希望这有帮助!

答案 1 :(得分:0)

您可以使用setInterval()函数在给定时间段内调用特定函数。因此,您刚刚编写了一个更新函数来更新图形并将其设置为setInterval函数的参数。

例如:

<!DOCTYPE HTML>
<html>
<head>
<script>
window.onload = function () {

var dps1 = []; // dataPoints
var dps2 = []; // dataPoints
var dps3 = []; // dataPoints
var dps4= []; // dataPoints

var chart = new CanvasJS.Chart("chartContainer", {
    title :{
        text: "Dynamic Data"
    },
    axisY: {
        includeZero: false
    },      
    data: [{
        type: "spline",
        dataPoints: dps1
    },{
        type: "spline",
        dataPoints: dps2
    },{
        type: "spline",
        dataPoints: dps3
    },{
        type: "spline",
        dataPoints: dps4
    }
    ]
});

var xVal = 0;
var yVal = 100; 
var updateInterval = 1000;
var dataLength = 20; // number of dataPoints visible at any point

var updateChart = function (count) {

    count = count || 1;

    for (var j = 0; j < count; j++) {
        yVal = yVal +  Math.round(5 + Math.random() *(-5-5));
        dps1.push({
            x: xVal,
            y: yVal
        });
        yVal = yVal +  Math.round(5 + Math.random() *(-5-5));
        dps2.push({
            x: xVal,
            y: yVal
        });
        yVal = yVal +  Math.round(5 + Math.random() *(-5-5));
        dps3.push({
            x: xVal,
            y: yVal
        });
        yVal = yVal +  Math.round(5 + Math.random() *(-5-5));
        dps4.push({
            x: xVal,
            y: yVal
        });

        xVal++;
    }

    if (dps1.length > dataLength) {
        dps1.shift();
    }
    if (dps2.length > dataLength) {
        dps2.shift();
    }
    if (dps3.length > dataLength) {
        dps3.shift();
    }
    if (dps4.length > dataLength) {
        dps4.shift();
    }

    chart.render();
};

updateChart(dataLength);
setInterval(function(){updateChart()}, updateInterval);

}
</script>
</head>
<body>
<div id="chartContainer" style="height: 370px; max-width: 920px; margin: 0px auto;"></div>
<script src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>
</body>
</html>

在这里,我每隔一秒钟更新一次图表。