размер графика d3 не обновляется

d3.js

153 просмотра

2 ответа

144 Репутация автора

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

Почему я могу обновлять значения для столбцов на графике, но не изменять количество баров при изменении размера набора данных?

Мой код ниже, и в этой скрипке .

    <html>
    <body>
    <div id="disp"></div> 
    <script src="https://d3js.org/d3.v3.min.js"></script>
    <script>

    var main = function () {
        console.log(dataset.toString())
        var a  = { a: 'temp', b: 50+Math.floor(Math.random() * 30)}
        var b = { a: 'hum', b: 20+Math.floor(Math.random() * 20)}

        // add new elements
        dataset.push(a);    
        dataset.push(b);

       // limit to 8 elements
        if(dataset.length > 8){ 
        dataset.shift(); 
        dataset.shift();
        }
        //update graph
        update(dataset); 

    }

      // dataset below will show 6 bars animating
     // var dataset = [{ a: 'temp', b: 5},{ a: 'hum', b: 8},{ a: 'temp', b: 4},
     // { a: 'hum', b: 9},{ a: 'temp', b: 15},{ a: 'hum', b: 12}];

    var dataset = [{ a: 'temp', b: 5},{ a: 'hum', b: 8}];


    var w = 600;
    var h = 250;

    var xScale = d3.scale.ordinal()
            .domain(d3.range(dataset.length))
            .rangeRoundBands([0, w], 0.1);

    var rectw = 20;
    var yScale = d3.scale.linear()
            .domain([0, 80])
            .range([0, h]);

    var svg = d3.select("body")
            .append("svg")
            .attr("width", w)
            .attr("height", h);

    var bars = svg.selectAll("g")
            .data(dataset);

    barsenter = bars.enter()
            .append('g')
            .attr('class', 'bars');


    barsenter
       .append("rect")
           .attr('class', 'temp')
       .filter(function(d){ return d.a == 'temp'})
       .attr("x", function(d, i) {
            return (rectw+2)*i*2;
       })
       .attr("y", function(d) {
            return h - yScale(d.b);
       })
       .attr("width", rectw)
       .attr("height", function(d) {
            return yScale(d.b);
       })
       .attr("fill", function(d) {
            return "rgb(" + (d.b * 4) +",0, 0)";
       });

    barsenter
       .append("rect")
           .attr('class', 'hum')
       .filter(function(d){ return d.a == 'hum'})
       .attr("x", function(d, i) {
            return rectw+2+(rectw+2)*i*2;
       })
       .attr("y", function(d) {
            return h - yScale(d.b);
       })
       .attr("width", rectw)
       .attr("height", function(d) {
            return yScale(d.b);
       })
       .attr("fill", function(d) {
            return  "rgb(0, 0, " + (d.b * 5) + ")";
       });


    // update function
    var update = function(dataset) {  

    bars.select(".temp")
       .data(dataset)
           .filter(function(d){ return d.a == 'temp'})
       .transition()
       .delay(function(d, i) {
           return i / dataset.length * 1000;
       })
       .duration(500)
       .attr("y", function(d) {
            return h - yScale(d.b);
       })
       .attr("height", function(d) {
            return yScale(d.b);
       })
       .attr("fill", function(d) {
            return "rgb(" + (d.b * 4) +",0, 0)";
       });

    bars.select(".hum")
       .data(dataset)
           .filter(function(d){ return d.a == 'hum'})
       .transition()
       .delay(function(d, i) {
           return i / dataset.length * 1000;
       })
       .duration(500)
       .attr("y", function(d) {
            return h - yScale(d.b);
       })
       .attr("height", function(d) {
            return yScale(d.b);
       })
       .attr("fill", function(d) {
            return  "rgb(0, 0, " + (d.b * 5) + ")";
       });

    }


    main();
    window.setInterval(function(){ main() }, 1000);

    </script>
    </body>
    </html>
Автор: oraz Источник Размещён: 18.07.2016 06:38

Ответы (2)


0 плюса

28936 Репутация автора

На вопрос: не меняется ли количество баров при изменении размера набора данных?

Причина, по которой вы создаете каналы только один раз, когда набор данных имеет только два значения.

barsenter
       .append("rect")

В разделе обновления вы не создаете, а просто обновляете прямоугольники значением.

Таким образом, исправление заключается в том, что в разделе обновлений также выполняется добавление.

Автор: Cyril Cherian Размещён: 18.07.2016 07:07

2 плюса

144 Репутация автора

Решение

После прочтения этих двух описаний, казалось, что понимание функций enter () и exit () в d3 является ключом.

Я сделал этот фрагмент, чтобы продемонстрировать гистограмму с функцией обновления.

//main code
// init data
var dataset = [];
function fillArray(arr){
 arr.push({'value' : Math.floor(Math.random()*50)});
}
for (var i = 0; i < 4; i++) {
fillArray(dataset);
}

// add 
var btnfunc = function(){
fillArray(dataset);
 //update graph
 update();
}

// remove 
var btnfunc2 = function(){
 dataset.pop()
//update graph
 update();
}

// randomize
var btnfunc3 = function(){
for (var i = 0; i < dataset.length; i++) { 
dataset[i].value = Math.floor(Math.random()*50);
}
//update graph 
update();
}


//d3 code
//init graph
var width = 700, height = 120;

var canvas = d3.select('#disp')
    .append('svg')
    .attr('width', width)
    .attr('height', height);

var x = d3.scale.linear()
        .domain([0, 10]) 
        .range([0, 700]);

var h = d3.scale.linear()
        .domain([0, 110])
        .range([0, height]); 

var y = d3.scale.linear()
        .domain([0, 80])
        .range([200, 0]);
//create selection
var bars = canvas.selectAll("rect");

//update function
function update(){
//update selection
bars = canvas.selectAll("rect").data(dataset);
//append new bars      
bars.enter().append("rect");
//bar attributes
bars
  .attr('width', 20)  
  .attr('height', function(d){ return h(d.value); }) 
  .attr('y', function(d){ return height - h(d.value); } )
  .attr('x', function (d, i) { return i*14*2; })
  .style('fill', 'red');
//remove bars
bars.exit().remove();

}

//1st display
update();
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="disp"></div> 
<button onclick="btnfunc()">add</button>
<button onclick="btnfunc2()">remove</button>
<button onclick="btnfunc3()">random</button>

Автор: oraz Размещён: 12.08.2016 10:21
Вопросы из категории :
32x32