2017-08-13 4 views
0

Gestern habe ich eine Frage zu einem Balkendiagramm gestellt, das ich nicht in alphabetischer Reihenfolge sortieren konnte. @Mark_M antwortete sehr freundlich und stellte mir eine gute Lösung zur Verfügung, die normalerweise perfekt funktionieren sollte. HierWarum sortiert mein xAxis nicht in d3?

ist das Snippet:

var xAxis = d3.axisBottom(xScale).tickSize(0) 

var sortBars = function() { 
    // Change domain based on sorted data 
    xScale.domain(data.sort(function(a, b) { 
     return d3.ascending(a.Region, b.Region); 
     }) 
     .map(function(d) {return d.Region}) 
    ) 

    // Redraw Rects with new position 
    svg.selectAll("rect") 
     .transition() 
     .duration(1000) 
     .attr("x", function(d, i) {return xScale(d.Region)}) 

    // Redraw x Axis 
    axeX.transition() 
    .duration(1000) 
    .call(xAxis) 

Die "rect" sind in der Tat Sortierung, aber die x-Achse (hier axeX genannt) gar nicht ändern. Es scheint, dass der Aufruf von xAxis (letzte Zeile) nicht funktioniert.

Haben Sie eine Vorstellung davon, was hier vor sich geht?

Hier wird der vollständige Code ist, ist der Sortierabschnitt ganz am Ende:

<!DOCTYPE html> 
<html> 
    <head> 
     <meta charset = "utf-8"> 
     <title>D3 Test</title> 
    </head> 
    <body> 
     <style> 
     div.tooltip {position: absolute;    
        text-align: center;    
        width: none;     
        height: none;     
        padding: none;    
        font: 12px futura; 
        color: thistle;   
        background: none; 
        border: 0px;  
        border-radius: 8px;    
        pointer-events: none;} 

     svg {background-color: none;} 


     .tooltip {font: 10px futura; 
        color: thistle;} 


     .axisX line{stroke: white;} 
     .axisX path{stroke: white;} 
     .axisX text{fill: black;} 

     .axisY line{stroke: black;} 
     .axisY path{stroke: white;} 


     .horizontalGrid line {stroke: lightgrey; 
           stroke-opacity: 0; 
           shape-rendering: crispEdges;} 
     .horizontalGrid path {stroke-width: 0;} 



     </style> 
     <script type ="text/javascript" src = d3/d3.js></script> 
     <script> 

     //Variables; dimensions du canevas 
     var margin = {top: 40, right: 20, bottom: 130, left: 120}, 
      svgWidth = 960 - margin.left - margin.right, 
      svgHeight = 400 - margin.top - margin.bottom, 
      barPadding = 2; 

     //Variables: domaines de l'Axe X et Y 
     var xScale = d3.scaleBand().range([0, svgWidth]).padding(0.1), //scaleBand pour des proportions 
      yScale = d3.scaleLinear().range([svgHeight, 0]); //scaleLinear pour des unités (noms, lettres) 

     //Variable: échelle de couleur divisée en 80 nuances entre deux couleurs 
     var colorScale = d3.scaleLinear().domain([0,80]).range(["white", "mediumturquoise"]); 

     //Variable: création du canevas dans <body> 
     var svg = d3.select("body") 
         .append("svg") 
         .attr("width", svgWidth + margin.left + margin.right) 
         .attr("height", svgHeight + margin.top + margin.bottom) 
         .append("g") 
         .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 

     //Variable: petit encadré qui apparait au passage de la souris 
     var div = d3.select("body") 
         .append("div") 
         .attr("class", "tooltip") 
         .style("visibility", "hidden"); 

     var absoluteView = false 




     //Variable: format des nombre lors de la transition de chargement des nombres -> https://github.com/d3/d3-format 
     var format = d3.format("d"); //d = notation décimale arrondie aux entiers 



     var xAxis = d3.axisBottom(xScale).tickSize(0) 


     //Biding: 
     d3.csv("/Users/daumardlouis/Desktop/geid3.csv", function(error, data) {if (error) throw error; 

      data.forEach(function(d) {d.Classification = +d.Classification;}); 

      xScale.domain(data.map(function(d) {return d.Region})); 
      yScale.domain([0, d3.max(data,function(d) {return d.Classification})]); 

     var xAxis = d3.axisBottom(xScale).tickSize(0) //marqueur d'échelle de taille 0 


      //Définition des barres 
      rect = svg.selectAll("rect") 
       .data(data) 
       .enter() 
       .append("rect") 
       .attr("x", function(d) {return xScale(d.Region)}) 
       .attr("width", svgWidth/data.length - barPadding) 
       .attr("y", svgHeight) // écart de l'axe Y = hauteur du canevas SVG 
       .attr("height", 0) // hauteur de départ des barres à 0 pour l'effet de transition 
       .attr("fill", function (d) {return colorScale (d.Classification)}) 
       .style("opacity", 0.9) 
       .on("mouseover",function(d) {d3.select(this).style("fill", "thistle").style("opacity", 0.5); // rempli de couleur la barre au passage de la souris 
              div.transition() // affiche le div en 0.2 secondes avec opacité de .5 
               .duration(200) 
               .style("visibility", "hidden"); 
              div.html(d.Classification) // affiche une donnée ou un texte dans le div 
               .style("left", (d3.event.pageX - 50) + "px") 
               .style("top", (d3.event.pageY - 70) + "px"); // la hauteur du div par rapport à la souris (attention en html la hauteur est inversée) 
              if(!absoluteView) { 
               var xPos = parseFloat(d3.select(this).attr("x")) + 6; 
               var yPos = parseFloat(d3.select(this).attr("y")) + 2; 
               var height = parseFloat(d3.select(this).attr("height")); 
               svg.append("text") 
               .attr("x", xPos) 
               .attr("y", yPos - 10) 
               .attr("class", "tooltip") 
               .text(d.Classification) 
               .attr("fill", "thistle")}; 



            }) 

       .on("mouseout",function(d) {d3.select(this).transition().duration(150).style("fill", function (d) {return colorScale (d.Classification)}).style("opacity", 1); // renvoie la couleur initiale à la sortie de la souris 
              div.transition() // faire disparaitre la div après .5 secondes 
               .duration(200) 
               .style("visibility", "hidden") 
              svg.select(".tooltip").remove(); 

              }); 

      //Transition des barres (rect) 
      rect.transition() 
       .delay(1000) 
       .ease(d3.easePoly) 
       .duration(500) 
       .attr("y", function(d) {return yScale(d.Classification)}) 
       .attr("height", function(d) {return svgHeight - yScale(d.Classification)}); 



      //Transition: effet de chargement progressif des nombres 
      var texte = svg.selectAll("text") 
      .data(data) 
      .enter() 
      .append("text") 
      .text(0) //texte à 0 au départ de la transition 
      .attr("x", function(d, i) {return 8 + i * (svgWidth/data.length)}) 
      .attr("y", svgHeight) // commence à 0, cad à la hauteur du canevas 
      .attr("fill", "thistle") 
      .attr("font-family", "futura") 
      .attr("font-size", "10px") 
      .transition() 
      .delay(function(d,i){return i *30}) //ajouter un délai décalé pour chaque élément de data 
      .ease(d3.easePoly) 
      .duration(900) 
      .attr("x", function(d, i) {return 8 + i * (svgWidth/data.length)}) 
      .attr("y", function(d) {return yScale(d.Classification) + (yScale(svgHeight)/16) }) 
      .tween("text", function(d) {var that = d3.select(this), 
              i = d3.interpolateNumber(that.text(), d.Classification); //donner une val de départ et de fin 
              return function(t) {that.text(format(i(t)))}}) //retourne le texte au format défini plus haut 
      .transition() 
      .delay(function(d,i){return 500 + i * (-30)}) //delay de 500 + annulation du délai décalé 
      .style("opacity", 0); 


      //Axe X, son style et ses transitions 
      var axeX = svg.append("g") 
       .attr("transform", "translate(0," + svgHeight + ")") 
       .call(xAxis) 
       .attr("class", "axisX") // récupère les indications de style de .axisX à l'interieur de la balise <style>. Utile pour changer la couleur de l'axe 
       .selectAll("text") 
       .attr("display", "true") 
       .attr("font-size", 2) 
       .attr("dx", "-4.8em") 
       .attr("dy", "4.15em") 
       .style("text-anchor", "end") //centre la fin du texte au milieu de chaque barre (rect) 
       .attr("transform", "rotate(-65)"); //effectue une rotation de -65° 


       axeX.transition() 
       .duration(500) 
       .delay(function(d,i){return i *30}) 
       .attr("font-family", "futura", "Bold") 
       .attr("font-size", 10); //style de police de caractère 




      //Axe Y, son style et ses transitions 
      var axeY = svg.append("g") 
       .attr("class", "axisY") 
       .attr("transform", "translate(-5)") 
       .transition() 
       .duration(5000) 
       .call(d3.axisLeft(yScale).tickSize(3)) 
       .selectAll("text") 
       .attr("transform", "translate(-5)") 
       .attr("font-family", "futura") 
       .attr("fill", "thistle"); //couleur de police de caractère 



      //Rajoute une légende à laxe Y 
      svg.append("g") 
      .append("text") 
      .attr("font-family", "futura") 
      .attr("font-size", 10) 
      .attr("transform", "rotate(-90)") 
      .attr("y", -48) 
      .attr("x", -68) 
      .style("text-anchor", "end") 
      .text(""); 



      //Rajoute des lignes de fonds prolongeant l'axe Y 
      svg.selectAll("axisY") 
       .data(yScale) 
       .enter() 
       .append("line") 
       .attr("class", "horizontalGrid") 
       .attr("x1", 0) 
       .attr("x2", svgWidth) 
       .attr("y1", function(d){ return yScale(d);}) 
       .attr("y2", function(d){ return yScale(d);}); 





      //Title 
      title = svg.append("text") 
       .attr("x", (svgWidth/2)) 
       .attr("y", 0 - (margin.top/2)) 
       .attr("text-anchor", "middle") 
       .attr("font-family", "futura") 
       .style("fill", "#5a5a5a") 
       .text("Nombre d'observations par régions"); 

       title.on("click", function() {sortBars()}); 



      // Sorting 

      var sortBars = function() {xScale.domain(data.sort(function(a, b) 
            {return d3.ascending(a.Region, b.Region)}).map(function(d) {return d.Region})) 

      // Redraw Rects with new position 
       svg.selectAll("rect") 
       .transition() 
       .duration(1000) 
       .attr("x", function(d, i) {return xScale(d.Region)}) 

      // Redraw x Axis 
       axeX.transition() 
        .duration(1000) 
        .call(xAxis) 

              } 


     }); 
     </script> 
    <body> 
</html> 

Antwort

2

Sie müssen sicherstellen, dass Sie die richtige Sache zu axeX sparen. Da Sie selectAll("text") daran angekettet haben, bezieht sich die Variable axeX auf den Text, nicht auf die Achse.

so etwas wie diese stattdessen versuchen:

//Axe X, son style et ses transitions 
    var axeX = svg.append("g") 
     .attr("transform", "translate(0," + svgHeight + ")") 
     .call(xAxis)   
     .attr("class", "axisX") // récupère les indications de style de .axisX à l'interieur de la balise <style>. Utile pour changer la couleur de l'axe 


    axeX.selectAll("text") 
     .attr("display", "true") 
     .attr("font-size", 2) 
     .attr("dx", "-10px") 
     .attr("dy", "10px") 
     .style("text-anchor", "end") //centre la fin du texte au milieu de chaque barre (rect) 
     .attr("transform", "rotate(-65)") //effectue une rotation de -65° 
     .transition() 
     .duration(500) 
     .delay(function(d,i){return i *30}) 
     .attr("font-family", "futura", "Bold") 
     .attr("font-size", 10); //style de police de caractère 

ich das dx und dy Attribut Pixel geändert, da die ems der Text springt um auf Refresh machen. Ich bin mir nicht ganz sicher, wie man mit ems den gewünschten Effekt erzielen kann. Ihr Wert ändert sich mit der Schriftgröße.

+0

Es funktioniert jetzt völlig ... Ich weiß nicht, was ich sagen soll, ich bin wirklich dankbar für Ihre Hilfe @Mark_M. Ich werde heute Abend zu Eurer Ehre Haendel-Menuett in g-Moll auf meinem Klavier spielen, Sir! – solub

Verwandte Themen