2017-08-19 1 views
0

J'ai un graphique à barres qui affiche data1.json ou data2.json en cliquant sur un bouton radio.Diagramme à barres d3 aligner les barres sur les graduations pour un nombre différent d'éléments

data1.json a 9 élément et data2.json a 4 éléments.

Question 1: Comment est-ce que je peux régler les choses de manière à ce que les barres soient toujours centrées sur les graduations, quel que soit le nombre d'objets ou de barres dans les données?

Question 2: Comment puis-je faire descendre l'axe X à l'endroit où vous vous attendez? Je sais que cela semble trivial, mais j'ai essayé plusieurs façons.

Question 3: Je voudrais vous assurer que la « valeur » est un numéro à l'aide

newdata.foreach(function(d) { 
     d.value = +d.value; 
    }) 

mais je ne semblent pas être en mesure de parcourir la « newdata » que je me attends . Il s'agit du github here et d'un gh-pages demo here.

Le fichier index.html

<!DOCTYPE html> 
<meta charset="utf-8"> 
<style> 
    .bar { 
    fill: steelblue; 
    } 
    .bar:hover { 
    fill: brown; 
    } 
    .axis text { 
    font: 10px sans-serif; 
    } 
    .axis path, 
    .axis line { 
    fill: none; 
    stroke: #000; 
    shape-rendering: crispEdges; 
    } 
</style> 

<body> 
    <form> 
    <input type="radio" name="inputsrc" id="defaultInput" value="default" checked=""><label for="defaultInput">data1.json</label> 
    <input type="radio" name="inputsrc" id="updateInput" value="post"><label for="updateInput">data2.json</label> 
    </form> 
    <svg id="d3newbie-chart" width="600" height="400"> 
    </svg> 
    <script src="https://d3js.org/d3.v4.min.js"></script> 

    <script type="text/javascript"> 
    var outerWidth = 600, 
     outerHeight = 400; 
    var margin = { 
     top: 40, 
     right: 30, 
     bottom: 30, 
     left: 80 
     }, 
     width = outerWidth - margin.left - margin.right, 
     height = outerHeight - margin.top - margin.bottom; 
    var x = d3.scaleBand() 
     .range([0, width]); 
    var y = d3.scaleLinear() 
     .range([height, 0]); 
    var xAxis = d3.axisBottom(x); 
    var yAxis = d3.axisLeft(y) 
     .ticks(10, "%"); 
    var chart = d3.select("#d3newbie-chart") 
     .attr("width", outerWidth) 
     .attr("height", outerHeight) 
     .append("g") 
     .attr("transform", "translate(" + margin.left + "," + margin.top + ")") 
    // x-axis 
    chart.append("g") 
     .attr("class", "x axis") 
     .attr("transform", "translate(0," + height + ")") 
     .call(xAxis); 

    function defaultFunction() { 
     d3.json("data1.json", function(error, newdata) { 
     if (error) throw error; 
     data = newdata; 
     // newdata.foreach(function(d) { 
     // d.value = +d.value; 
     // }) 
     update(); 
     }); 
    } 
    function updateFunction() { 
     d3.json("data2.json", function(error, newdata) { 
     if (error) throw error; 
     data = newdata; 
     update(); 
     }); 
    } 
    function update(err, newdata) { 
     y.domain([0, d3.max(data, function(d) { 
     return d.value; 
     })]); 
     x.domain(data.map(function(d) { 
     return d.name 
     })); 
     // x-axis 
     chart.select(".x.axis").remove(); 
     chart.append("g") 
     .attr("class", "x axis") 
     .call(xAxis) 
     .append("text") 
     .attr("transform", "rotate(-90)") 
     .attr("y", 6) 
     .attr("dy", ".71em") 
     .style("text-anchor", "end") 
     .text("Frequency"); 
     // y-axis 
     chart.select(".y.axis").remove(); 
     chart.append("g") 
     .attr("class", "y axis") 
     .call(yAxis) 
     .append("text") 
     .attr("transform", "rotate(-90)") 
     .attr("y", 6) 
     .attr("dy", ".71em") 
     .style("text-anchor", "end") 
     .text("Frequency"); 
     var bar = chart.selectAll(".bar") 
     .data(data, function(d) { 
      return d.name; 
     }); 
     // new data: 
     bar.enter().append("rect") 
     .attr("class", "bar") 
     .attr("x", function(d) { 
      return x(d.name); 
     }) 
     .attr("y", function(d) { 
      return y(d.value); 
     }) 
     .attr("height", function(d) { 
      return height - y(d.value); 
     }) 
     .attr("width", 20); 
     // removed data: 
     bar.exit().remove(); 
     // updated data: 
     bar.transition() 
     .duration(750) 
     .attr("y", function(d) { 
      return y(d.value); 
     }) 
     .attr("height", function(d) { 
      return height - y(d.value); 
     }); 
    }; 
    document.getElementById("defaultInput") 
     .onclick = defaultFunction; 
    document.getElementById("updateInput") 
     .onclick = updateFunction; 
    defaultFunction(); 
    </script> 
</body> 

Répondre

1

Code Mise à jour: https://jsfiddle.net/5j2nw238/2/

Question 1: La largeur des barres est déterminée par la largeur de la svg, ainsi que vos valeurs données pour les fonctions scaleBandpaddingInner, paddingOuter et quelques autres.

https://github.com/d3/d3-scale/blob/master/README.md#band-scales

Jetez un oeil à l'image décrivant ces paramètres. Le point est de ne pas coder en dur la largeur des barres comme vous l'avez fait avec .attr("width", 20);, et à la place manipuler le scaleBand pour trouver votre look désiré.

Question 2:

Vous avez fait cela correctement avec le code

chart.append("g") 
    .attr("class", "x axis") 
    .attr("transform", "translate(0," + height + ")") 
    .call(xAxis); 

Mais sur la mise à jour, vous supprimez l'axe et n'a pas appliqué le nouveau transform. Au lieu de supprimer l'axe et de le recréer, il suffit de mettre à jour l'échelle de l'axe avec le nouveau domaine et de faire chart.select(".x.axis").call(xAxis). Cela correspond à la façon de penser d3 selon les données. Changez vos données, et laissez D3 gérer le DOM.

Question 3:

Le nom de la fonction est forEach, pas foreach. En outre, vous dites que vous voulez vous assurer que la valeur est une chaîne, mais en mettant l'opérateur + avant qu'une variable le convertisse en un nombre, pas une chaîne.

+0

Des réponses brillantes, merci beaucoup. Je comprends complètement maintenant les questions 2 et 3. En fait, je m'assure que si les données sont une chaîne, elles seront converties en nombre. Il me faudra un peu de temps pour travailler sur la question 1. Le repo github reflète maintenant ces changements.Merci encore –

+0

Je vois maintenant que j'ai dit que je veux que la valeur soit une chaîne, je veux dire que je veux que la chaîne soit un nombre. –

+0

Je vois que vous avez tiré le json de github, je ne savais pas que c'était possible. Très utile! Je n'ai pas mis en place un Jsfiddle parce que je ne savais pas comment amener le JSON. Fantastique, merci encore! –