2017-05-08 1 views
0

J'ai un peu de mal à construire un graphique à barres. J'apprends d3.js pour la première fois et étant quelqu'un qui a toujours travaillé avec PHP/MySQL, je n'ai pas eu à apprendre le javascript. En conséquence, je me bats un peu.comment redimensionner automatiquement le graphique d3.js pour inclure l'axe

Ma question est de nature plus conceptuelle. Si, disons, dans un diagramme à barres, l'axe Y est contenu dans un élément g et que les barres sont contenues dans un autre, comment puis-je m'assurer que mon axe prend une largeur dynamique en fonction des données présentées?

J'ai réussi à générer un graphique à barres et cela fonctionne très bien, mais le remplissage est un nombre fixe (disons 50px). cela fonctionne très bien maintenant, parce que mes chiffres vont de 0 à 50, donc tout va bien. Que se passe-t-il si j'ai des trillions à la place? La largeur de l'axe va changer, mais mon remplissage reste 50px, ce qui signifie qu'il va couper mon contenu.

Quelle est la "convention" quand il s'agit de cela? Des astuces?

Merci

+0

Vous pouvez définir le remplissage = 0,1 * largeur par exemple – TheBiro

+0

grâce, mais c'est toujours une valeur fixe. il faudra toujours calculer en fonction de la largeur, sans tenir compte de la largeur du texte de mes étiquettes. existe-t-il un moyen de générer la largeur de l'élément courant? alors je pourrais utiliser la largeur du g contenant l'axe et compenser par cela. – Chris

+0

cela peut aider https://bl.ocks.org/curran/3a68b0c81991e2e94b19 – TheBiro

Répondre

0

Une astuce que vous pouvez utiliser ici est ce que j'appelle le « double-rendu ». Vous dessinez essentiellement l'axe en premier (avant le reste de l'intrigue) et obtenez la largeur de la plus grande étiquette graduée. Le, Vous pouvez dessiner l'intrigue de manière conventionnelle avec cette valeur comme marge. Cette astuce est particulièrement utile pour les libellés "catégorie" de chaîne, mais fonctionnera également pour les nombres.

Voici un exemple commenté. Exécuter plusieurs fois pour voir comment il radoub l'axe:

<!DOCTYPE html> 
 
<meta charset="utf-8"> 
 
<style> 
 
    .bar { 
 
    fill: steelblue; 
 
    } 
 
    
 
    .bar:hover { 
 
    fill: brown; 
 
    } 
 
    
 
    .axis--x path { 
 
    display: none; 
 
    } 
 
</style> 
 
<svg width="300" height="300"></svg> 
 
<script src="//d3js.org/d3.v4.min.js"></script> 
 
<script src="//chancejs.com/chance.min.js"></script> 
 
<script> 
 

 

 
    // set up some random data 
 
    // pick a random max value to render on the yaxis 
 
    var maxVal = chance.integer({ 
 
     min: 1, 
 
     max: chance.pickone([1e1, 1e5, 1e10]) 
 
    }), 
 
    // generate some fake data 
 
    data = [{ 
 
     x: chance.word(), 
 
     y: chance.floating({ 
 
     min: 0, 
 
     max: maxVal 
 
     }) 
 
    }, { 
 
     x: chance.word(), 
 
     y: chance.floating({ 
 
     min: 0, 
 
     max: maxVal 
 
     }) 
 
    }, { 
 
     x: chance.word(), 
 
     y: chance.floating({ 
 
     min: 0, 
 
     max: maxVal 
 
     }) 
 
    }, { 
 
     x: chance.word(), 
 
     y: chance.floating({ 
 
     min: 0, 
 
     max: maxVal 
 
     }) 
 
    }]; 
 

 
    // create svg and set up a y scale, the height value doesn't matter 
 
    var svg = d3.select("svg"), 
 
    y = d3.scaleLinear().rangeRound([100, 0]); 
 

 
    // set domain 
 
    y.domain([0, d3.max(data, function(d) { 
 
    return d.y; 
 
    })]); 
 

 
    // draw fake axis 
 
    var yAxis = svg.append("g") 
 
    .attr("class", "axis axis--y") 
 
    .call(d3.axisLeft(y)); 
 

 
    // determine max width of text label 
 
    var mW = 0; 
 
    yAxis.selectAll(".tick>text").each(function(d) { 
 
    var w = this.getBBox().width; 
 
    if (w > mW) mW = w; 
 
    }); 
 

 
    // remove fake yaxis 
 
    yAxis.remove(); 
 

 
    // draw plot normally 
 
    var margin = { 
 
     top: 20, 
 
     right: 20, 
 
     bottom: 30, 
 
     left: mW + 10 // max with + padding fudge 
 
    }, 
 
    width = +svg.attr("width") - margin.left - margin.right, 
 
    height = +svg.attr("height") - margin.top - margin.bottom; 
 

 
    var g = svg.append("g") 
 
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 
 

 
    // reset to actual height 
 
    y.range([height, 0]); 
 

 
    var x = d3.scaleBand().rangeRound([0, width]).padding(0.1); 
 

 
    x.domain(data.map(function(d) { 
 
    return d.x; 
 
    })); 
 

 
    g.append("g") 
 
    .attr("class", "axis axis--x") 
 
    .attr("transform", "translate(0," + height + ")") 
 
    .call(d3.axisBottom(x)); 
 

 
    g.append("g") 
 
    .attr("class", "axis axis--y") 
 
    .call(d3.axisLeft(y)); 
 

 
    g.selectAll(".bar") 
 
    .data(data) 
 
    .enter().append("rect") 
 
    .attr("class", "bar") 
 
    .attr("x", function(d) { 
 
     return x(d.x); 
 
    }) 
 
    .attr("y", function(d) { 
 
     return y(d.y); 
 
    }) 
 
    .attr("width", x.bandwidth()) 
 
    .attr("height", function(d) { 
 
     return height - y(d.y); 
 
    }); 
 
</script>

+0

exactement ce que je cherche, merci un million! solution brillante ... – Chris