2012-06-28 6 views
0

Je veux dessiner trois carrés contigus avec des couleurs différentes (ce n'est pas un problème, c'est dans la variable "échelle") et mettre un nombre variable de petits carrés sous chaque grande couleur (que je ne peux pas faire, les "points" variable). Qu'est-ce que je fais mal? Ceci est mon code, et le https://gist.github.com/3013836 essentiel:comment imbriquer des sélections dans d3?

var data = [-1,0,1] 

var rect_size = 25; //px 

var x = d3.scale.ordinal().domain(d3.range(data.length)).rangeBands([0, rect_size*data.length]); 
var color = d3.scale.linear().domain([-1.5, 0, 1.5]).range(["#278DD6","#ffffff","#d62728"]).clamp(false); 

var svg = d3.select("body").append("svg") 
    .attr("width", 800) 
    .attr("height", 200) 

scale = svg.selectAll("rect") 
    .data(data) 
    .enter().append("rect") 
    .attr("x", function(d,i) { return x(i); }) 
    .attr("y",0) 
    .attr("width", rect_size) 
    .attr("height", rect_size) 
    .style("fill", function(d) { return color(d); }); 

dots = [[1,2,3],[1,2],[1,2,3,4]] 
var y = d3.scale.ordinal().domain(d3.range(dots.length)).rangeBands([0, (rect_size/2)*dots.length]); 
scale.selectAll("g") 
    .data(dots, function(d){return d;}) 
    .enter().append("rect") 
    .attr("x", function(d,i) {return x(i);}) 
    .attr("y", function(d,i) {return y(i);}) 
    .attr("width", rect_size/2) 
    .attr("height", rect_size/2) 
    .style("fill", "black"); 

Répondre

1

Vous avez défini la sélection scale que trois éléments rect. Ensuite, vous avez ajouté trois éléments rect supplémentaires dans chacun de ceux-ci. si vous utilisez l'inspecteur de l'élément de votre navigateur, la structure résultante, ressemblera à ceci:

<rect class="outer"> 
    <rect class="inner"></rect> 
    <rect class="inner"></rect> 
    <rect class="inner"></rect> 
</rect> 

Cela ne affiche trois rects parce rects ne sont pas container elements en SVG; les retours internes sont ignorés.

Si vous souhaitez regrouper des éléments, vous avez besoin d'un g (group) element. Vous voulez une structure comme ceci:

<g> 
    <rect class="outer"></rect> 
    <rect class="inner"></rect> 
    <rect class="inner"></rect> 
    <rect class="inner"></rect> 
</g> 

Vous pouvez le faire en créant d'abord une sélection d'éléments g en utilisant un data-join. Puis append un seul rect externe aux éléments g. Et enfin utiliser un nested join pour créer les retours internes. Quelque chose comme:

var g = svg.selectAll("g") 
    .data(outerData) 
    .enter().append("g"); 

var outerRect = g.append("rect") 
    .attr("class", "outer"); 

var innerRect = g.selectAll(".inner") 
    .data(innerData) 
    .enter().append("rect") 
    .attr("class", "inner"); 

Quelques autres:

  • Vous pouvez utiliser une transformation sur les éléments g de sorte que vous ne devez pas placer les rects interne et externe séparément. De cette façon, les rects internes peuvent être positionnés par rapport aux rects externes et le code est plus simple.

  • Votre dernière jointure est rompue car vous sélectionnez "g" et ajoutez "rect"; tout ce que vous ajoutez doit correspondre à votre sélecteur.

  • Vous n'avez généralement pas besoin de key function avec votre jointure de données, sauf si vous gérez également la mise à jour et la sortie. Puisque vous ne gérez que votre entrée, et que vous savez que la sélection est vide, la fonction de clé est inutile.

+0

Génial! Vous venez de clarifier mon brouillard mental. Je pense que j'ai enfin compris – nachocab

Questions connexes