简体   繁体   English

D3 - 每 2 秒更新条形图

[英]D3 - Update bar chart per 2 seconds

I have a D3 bar chart, with some data drawn initially.我有一个 D3 条形图,最初绘制了一些数据。 I will be getting new data per 2 seconds.我将每 2 秒获取新数据。 This new data could be new items or new counts for existing items.此新数据可以是新项目或现有项目的新计数。 I want to update the chart accordingly.我想相应地更新图表。

This is what I have tried:这是我试过的:

https://jsfiddle.net/rutwick/an1d95h1/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();

It updates, but doesn't redraw the chart.它会更新,但不会重绘图表。 Just adds the new bars over the old ones.只需在旧条上添加新条。 My current plan includes removing all the rect elements using jQuery, but I don't know if it will work.我目前的计划包括使用 jQuery 删除所有 rect 元素,但我不知道它是否可行。

What exactly needs to be done to update the complete chart, both on x and y axes?在 x 轴和 y 轴上更新完整图表究竟需要做什么?

You can do it this way:你可以这样做:

First you need to define the object like this:首先,您需要像这样定义对象:

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

Now create rectangle like this:现在像这样创建矩形:

  newRects.append('rect');

Now update all the rect with new width and height.现在用新的宽度和高度更新所有的矩形。

  //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);
  });

Finally remove bars for which data has been removed:最后删除已删除数据的柱:

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

The problem why your code was not updating:您的代码未更新的问题:

When you do this the attribute update only on 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);
    });

Working code here工作代码在这里

Hope this helps!希望这可以帮助!

You can use setInterval() function to call particular function for a given period.您可以使用 setInterval() 函数在给定时间段内调用特定函数。 So you just written an update function to update graph and set it as an argument of setInterval function.所以你刚刚编写了一个更新函数来更新图形并将其设置为 setInterval 函数的参数。

For Example:例如:

<!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>

Here I update my chart in every one seconds.在这里,我每隔一秒更新一次图表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM