2013-06-14 6 views
7

Ich zeichne Liniendiagramme mit d3 und alles funktioniert gut. Allerdings muss ich auf der linken Seite des Diagrammbereichs genügend Rand belassen, um zu passen, was ich für das breiteste y-Achsen-Textlabel halte. Ich möchte diesen Platz für jedes Diagramm anpassen, abhängig von der breitesten Bezeichnung.Y-Achse des D3-Diagramms so einstellen, dass sie auf das breiteste Etikett passt?

Anfangs dachte ich, ich könnte den maximalen y-Wert finden, ein verstecktes Textobjekt erstellen, herausfinden, wie breit das ist und diesen Wert für den linken Rand verwenden, wenn ich das Diagramm erstelle. Ein bisschen eklig, aber es bringt mir einen Wert.

Wenn jedoch der maximale y-Wert ist, sagen wir "1598.538", könnte die oberste y-Achsen-Marke "1500" sein ... dh viel enger.

Also ich denke, ich möchte die Breite von was auch immer das oberste Label sein wird. Aber ich kann mir nicht vorstellen, wie ich das machen soll, ohne das Diagramm und die Achse zu zeichnen, diese Breite zu messen und sie wieder real zu zeichnen. Was klingt fies! Gibt es eine nicht-böse Art, dies zu tun?

UPDATE

Hier ist ein Teil meines Code, mit Lars-Vorschlag, nur um zu zeigen, wo es hingehört:

// I did have 
// `.attr("transform", "translate(" + margin.left + "," + margin.top ")")` 
// on the end of this line, but I've now moved that to the bottom. 
var g = svg.select("g"); 

// Add line paths. 
g.selectAll(".line").data(data) 
    .enter() 
    .append("path") 
    .attr("d", line); 

// Update the previously-created axes. 
g.select(".axis-x") 
    .attr("transform", "translate(0," + yScale.range()[0] + ")")) 
    .call(xAxis); 
g.select(".axis-y") 
    .call(yAxis); 

// Lars's suggestion for finding the maximum width of a y-axis label: 
var maxw = 0; 
d3.select(this).select('.axis-y').selectAll('text').each(function(){ 
    if (this.getBBox().width > maxw) maxw = this.getBBox().width; 
}); 

// Now update inner dimensions of the chart. 
g.attr("transform", "translate(" + (maxw + margin.left) + "," + margin.top + ")"); 

Antwort

6

Sie können alles in einem g Element setzen und Set transform basierend auf die maximale Breite. Etwas im Sinne von

var maxw = 0; 
yAxisContainer.selectAll("text").each(function() { 
    if(this.getBBox().width > maxw) maxw = this.getBBox().width; 
}); 
graphContainer.attr("transform", "translate(" + maxw + ",0)"); 
+0

Ausgezeichnet, nochmals vielen Dank Lars! Ich aktualisiere meine Frage mit einem weiteren Codebeispiel, um zu zeigen, wo ich Ihren Vorschlag in Bezug auf andere Teile des Diagrammzeichnungscodes gesetzt habe. –

+0

Nachdem das gesagt wurde ... während es den perfekten Platz für die linke Achse belässt, wird der Diagrammbereich nach rechts verschoben, wodurch die rechte Kante des Diagramms und der x-Achse abgeschnitten wird. Ich bin mir nicht sicher, wie ich das beheben soll - kommt es nicht von der Skala der x-Achse, die früher eingestellt werden sollte? –

+0

Sie können auch zuerst die y-Achse zeichnen, dann messen und dann den x-Achsenbereich entsprechend einstellen und den Rest des Diagramms zeichnen. Da die Elemente der Y-Achse bereits vorhanden sind, können Selektoren, die Sie zum Zeichnen des restlichen Graphen verwenden ('.selectAll ('path')', '.selectAll ('text')'), jedoch vorsichtig sein. –