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