为什么我的xAxis没有在d3中排序?

时间:2017-08-13 11:26:27

标签: sorting d3.js graph

昨天我发布了一个关于条形图的问题,我不知道如何按字母顺序排序。 @Mark_M非常友好地回答并为我提供了一个通常应该完美的解决方案。

以下是摘录:

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)

"rect"确实是排序,但x轴(此处称为axeX)根本没有变化。似乎调用xAxis(最后一行)不起作用。

知道这里发生了什么吗?

以下是完整的代码,排序部分位于最后:

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

1 个答案:

答案 0 :(得分:2)

您需要确保将正确的内容保存到axeX。因为您已将selectAll("text")链接到它,axeX变量指的是文本而不是轴。

尝试这样的事情:

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

我将dxdy属性更改为像素,因为ems使文本在刷新时跳转。我不太确定如何使用ems获得你想要的效果。它们的值随字体大小而变化。