2016-09-16 3 views
1

Verlassen habe ich ein Balkendiagramm in D3.js wo, wenn ein Benutzer ap Tag klickt, sagtD3.js Balkendiagramm Animation nicht korrekt

hier klicken bar entfernen

dann sollte es Entferne den linken Balken. Für die Animation möchte ich, dass die Leiste links vom Bildschirm wegfliegt, und dann werden die anderen Balken in ihre korrekte Position gebracht. Das Problem ist jedoch, dass das rechte Balkendiagramm stattdessen entfernt wird, ein anderer Balken wird außerhalb des Diagramms verschoben und kann nicht mehr angezeigt werden, und es sieht so aus, als ob die Werte der Balken geändert werden.

Ich habe eine jsfiddle, die dieses Problem neu zu erstellen ist in der Lage: jsFiddle

Hier ist auch der JavaScript-Code, der die Erstellung ausgeführt wird, und Animation für das Balkendiagramm:

// chart dimensions 
var margin = { top: 20, right: 30, bottom: 20, left: 70 }, 
    width = $('#chart').width() - margin.left - margin.right, 
    height = $(window).height()/3.5 - margin.top - margin.bottom; 

// color palette for graph 
var colors = [ '#4398B5', '#ADC4CC', '#92B06A', '#E09D2A', '#DE5F32' ]; 

var dataset = [ 100, 200, 300, 400, 500 ]; 

var xScale = d3.scaleBand() 
       .domain(d3.range(dataset.length)) 
       .range([ 0, width ]) 
       .padding(0.1); 


var yScale = d3.scaleLinear() 
       .domain([ 0, d3.max(dataset) ]) 
       .range([ height, 0 ]); 


var xAxis = d3.axisBottom(xScale); 
var yAxis = d3.axisLeft(yScale); 

var svg = d3.select('#chart svg') 
      .attr('width' , width + margin.left + margin.right ) 
      .attr('height' , height + margin.top + margin.bottom) 
      .append('g') 
       .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); 

svg.selectAll('rect') 
    .data(dataset) 
    .enter() 
    .append('rect') 
     .attr('x', function (d, i) { 
      return xScale(i); 
     }) 
     .attr('width', xScale.bandwidth()) 
     .attr('fill', function(d, i) { 
      return colors[ i ]; 
     }) 
     .attr('y', function(d, i) { 
      return yScale(d); 
     }) 
     .attr('height', function(d) { 
      return height - yScale(d); 
     }); 

svg.append('g') 
    .attr('class', 'yAxis') 
    .attr('transform', 'translate(0, ' + (-1) + ')') 
    .call(yAxis); 

d3.select("p") 
     .on("click", function() { 

      dataset.shift(); 
      //Update scale domains 
      xScale.domain(d3.range(dataset.length)); 
      yScale.domain([ 0 , d3.max(dataset) ]); 

      //Select… 
      var bars = svg.selectAll("rect") 
          .data(dataset); 

      bars.transition() 
       .duration(500) 
       .attr("x", function(d, i) { 
        return xScale(i); 
       }) 
       .attr("y", function(d) { 
        return height - yScale(d); 
       }) 
       .attr("width", xScale.bandwidth()) 
       .attr("height", function(d) { 
        return yScale(d); 
       }); 

      bars.exit() 
       .transition() 
       .duration(500) 
       .attr("x", -xScale.bandwidth()) 
       .remove(); 
      }); 

Jede mögliche Hilfe sehr geschätzt werden.

Danke!

Antwort

1

Lesen Sie den Abschnitt der d3 Dokumente auf .data 's key function.

Standardmäßig verwendet d3 Elementindex als Schlüsselfunktion. Wenn Sie Ihre Daten .shift eingeben, denkt es, dass der letzte Index das ausstehende Element ist, da die Länge um Eins verringert wird. Der richtige Weg, um dies zu beheben, besteht darin, Ihre Daten so zu modifizieren, dass jedes Datum eine eindeutige Kennung hat. Sie wollen wirklich Daten hier gefahren werden, so würde ich so etwas tun:

var dataset = [ 
{ 
    value: 100, 
    color: '#4398B5', 
    id: 1 
},{ 
    value: 200, 
    color: '#ADC4CC', 
    id: 2 
},{ 
    value: 300, 
    color: '#92B06A', 
    id: 3 
},{ 
    value: 400, 
    color: '#E09D2A', 
    id: 4 
},{ 
    value: 500, 
    color: '#DE5F32', 
    id: 5 
}]; 

Ihre Schlüsselfunktion ist dann:

.data(dataset, function(d){ return d.id; }) 

Hinweis, ich eine ID in den Daten hinzugefügt, aber man konnte habe auch nur Farbe verwendet, solange es einzigartig ist.

Hier ist eine schnelle refactor mit einem verbesserten Daten-Array.

+0

Ich sehe, das macht Sinn. Aber selbst mit dem Refactor sieht es immer noch so aus, als ob es das Dataset auf dem Balkendiagramm wechselt, und zeigt den falschen Balken an, um zu beenden. Ist das immer noch ein Produkt der '.shift' Funktion? Ich habe stattdessen '.splice' versucht und sogar ein neues Array mit einem entfernten Element erstellt, aber ohne Glück. – ans

+1

@ans, deine 'y' und' height' Berechnungen sind rückwärts in deiner Update Funktion. Aktualisierte Geige oben. – Mark

+0

Yup das war es! Vielen Dank! – ans