最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - D3.js update bar chart from json - Stack Overflow

programmeradmin1浏览0评论

I'm working on a bar chart using d3.js, the bar shoud be able correspond to a new json data.

var m = [30, 5, 5, 5],
    w = 375 - m[1] - m[3],
    h = 260 - m[0] - m[2];

var format = d3.format(",.0f");

var wdthnew = d3.scale.linear().range([0, w]),
    wdth = d3.scale.linear().range([0, w]).domain([0, 25000]),
    hght = d3.scale.ordinal().rangeRoundBands([0, h], .1);

var svg = d3.select("body").append("svg")
    .attr("width", w + m[1] + m[3])
    .attr("height", h + m[0] + m[2])
  .append("g")
    .attr("transform", "translate(" + m[3] + "," + m[0] + ")");

d3.json("barchartjson.php", function(data) {

  data.sort(function(a, b) { return b.value - a.value; });
  hght.domain(data.map(function(d) { return d.orientation; }));

  var bar = svg.selectAll("g.bar")
      .data(data)
    .enter().append("g")
      .attr("class", "bar")
      .attr("transform", function(d) { return "translate(0," + hght(d.orientation) + ")"; });

  bar.append("rect")
      .attr("id", "activebar") 
      .attr("width", 0)
      .attr("height", hght.rangeBand())
    .transition()
    .delay(100)
    .duration(1000)    
      .attr("width", function(d) { return wdth(d.value); });    
});

function makebar(date1, date2) {
var barchartjson = "barchartjson.php?df="+date1+"&dl="+date2;

d3.json(barchartjson , function(datanew) { 

  datanew.sort(function(a, b) { return b.jumlah - a.jumlah; });

  wdthnew.domain([0, d3.sum(datanew, function(d) { return d.value; })]);

  console.log("SUM datanew: "+ d3.sum(datanew, function(d) { return d.value; }));
  console.log("Array datanew: ");
  console.log(datanew);
  var updatebar = svg.selectAll("#activebar");

  updatebar.transition().duration(1000)
        .attr("width", function(a) { console.log("update width: wdthnew("+a.value+") = "+wdthnew(a.value));
        return wdthnew(a.value); });  
});
}

Here is the json from barchartjson.php used at the first time:

[{"orientation":"negatif","value":"15964"},{"orientation":"netral","value":"2788"},{"orientation":"positif","value":"9701"}]

The bar is showing properly for the first time. The problem is when makebar() is called, updating the bar width with the new json data. Each bar width is updated, but in some case they are out of range. Here is the output from console.log :

SUM datanew: 2520
Array datanew: 
[Object
value: "1411"
orientation: "negatif"
__proto__: Object
, 
Object
value: "846"
orientation: "positif"
__proto__: Object
, 
Object
value: "263"
orientation: "netral"
__proto__: Object
]
update width: wdthnew(15964) = 2312.246031746032
update width: wdthnew(9701) = 1405.1051587301588
update width: wdthnew(2788) = 403.81746031746036

a new json successfully called , but the log showing that wdthnew is keep scaling the old json.

 updatebar.transition().duration(1000)
        .attr("width", function(a) { console.log("update width: wdthnew("+a.value+") = "+wdthnew(a.value));
        return wdthnew(a.value); }); 

resulting:

update width: wdthnew(15964) = 2312.246031746032

despite 15694 is from the old json, the wdthnew(d.value) is actually return a value from wdthnew(1411) wich is 2312 and it is out of range..

Can someone help me solve this problem? Or point out where I'm doing wrong? I'm new to d3.js and javascript. I'm sorry for the bad grammar. English is not my native language.

jsFiddle here: /

I'm working on a bar chart using d3.js, the bar shoud be able correspond to a new json data.

var m = [30, 5, 5, 5],
    w = 375 - m[1] - m[3],
    h = 260 - m[0] - m[2];

var format = d3.format(",.0f");

var wdthnew = d3.scale.linear().range([0, w]),
    wdth = d3.scale.linear().range([0, w]).domain([0, 25000]),
    hght = d3.scale.ordinal().rangeRoundBands([0, h], .1);

var svg = d3.select("body").append("svg")
    .attr("width", w + m[1] + m[3])
    .attr("height", h + m[0] + m[2])
  .append("g")
    .attr("transform", "translate(" + m[3] + "," + m[0] + ")");

d3.json("barchartjson.php", function(data) {

  data.sort(function(a, b) { return b.value - a.value; });
  hght.domain(data.map(function(d) { return d.orientation; }));

  var bar = svg.selectAll("g.bar")
      .data(data)
    .enter().append("g")
      .attr("class", "bar")
      .attr("transform", function(d) { return "translate(0," + hght(d.orientation) + ")"; });

  bar.append("rect")
      .attr("id", "activebar") 
      .attr("width", 0)
      .attr("height", hght.rangeBand())
    .transition()
    .delay(100)
    .duration(1000)    
      .attr("width", function(d) { return wdth(d.value); });    
});

function makebar(date1, date2) {
var barchartjson = "barchartjson.php?df="+date1+"&dl="+date2;

d3.json(barchartjson , function(datanew) { 

  datanew.sort(function(a, b) { return b.jumlah - a.jumlah; });

  wdthnew.domain([0, d3.sum(datanew, function(d) { return d.value; })]);

  console.log("SUM datanew: "+ d3.sum(datanew, function(d) { return d.value; }));
  console.log("Array datanew: ");
  console.log(datanew);
  var updatebar = svg.selectAll("#activebar");

  updatebar.transition().duration(1000)
        .attr("width", function(a) { console.log("update width: wdthnew("+a.value+") = "+wdthnew(a.value));
        return wdthnew(a.value); });  
});
}

Here is the json from barchartjson.php used at the first time:

[{"orientation":"negatif","value":"15964"},{"orientation":"netral","value":"2788"},{"orientation":"positif","value":"9701"}]

The bar is showing properly for the first time. The problem is when makebar() is called, updating the bar width with the new json data. Each bar width is updated, but in some case they are out of range. Here is the output from console.log :

SUM datanew: 2520
Array datanew: 
[Object
value: "1411"
orientation: "negatif"
__proto__: Object
, 
Object
value: "846"
orientation: "positif"
__proto__: Object
, 
Object
value: "263"
orientation: "netral"
__proto__: Object
]
update width: wdthnew(15964) = 2312.246031746032
update width: wdthnew(9701) = 1405.1051587301588
update width: wdthnew(2788) = 403.81746031746036

a new json successfully called , but the log showing that wdthnew is keep scaling the old json.

 updatebar.transition().duration(1000)
        .attr("width", function(a) { console.log("update width: wdthnew("+a.value+") = "+wdthnew(a.value));
        return wdthnew(a.value); }); 

resulting:

update width: wdthnew(15964) = 2312.246031746032

despite 15694 is from the old json, the wdthnew(d.value) is actually return a value from wdthnew(1411) wich is 2312 and it is out of range..

Can someone help me solve this problem? Or point out where I'm doing wrong? I'm new to d3.js and javascript. I'm sorry for the bad grammar. English is not my native language.

jsFiddle here: http://jsfiddle/saido/5mREA/

Share Improve this question edited May 3, 2012 at 19:38 ZachB 15.5k5 gold badges66 silver badges93 bronze badges asked Apr 25, 2012 at 11:24 FrendhiFrendhi 791 silver badge7 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 3

Turns out the problem was in function makebar(): at this line I supposed to attach the new data:

var updatebar = svg.selectAll("#activebar").data(datanew);

Now the console.log showing and calculating the proper values.

I'm sorry I'm not sure how to explain the technical issue in much more detail.

Perhaps create a buffer array/object that will store the data prior to using it... Then create an update interval that won't update before new data arrives.

Update: Here's an example

var data = [{x: 1, y: 3},
            {x: 2, y: 4},
            {x: 3, y: 5},
            ...
            ];

var iningData = [];

/* ining data gets .pushed(...) in every 1 or
    2 seconds, depending on network traffic */

var updateDelay = 3000;

setInterval(function() {
        for (var index = 0; index < data.length; index++) {
            seriesData.shift();
            seriesData.push(iningData.shift());
            redrawGraph();
        }
    }, updateDelay);
发布评论

评论列表(0)

  1. 暂无评论