2014-07-08 12 views
6

Ich verwende NVD3.js multiChart, um mehrere Linien und Balken im Diagramm anzuzeigen. Alles funktioniert gut, aber die X-Achsenbeschriftungen sind nur auf die Linienpunkte ausgerichtet, nicht auf Balken. Ich möchte die Etiketten direkt unterhalb der Balken korrekt ausrichten. Aber ich bekomme diese:NVD3.js multiChart X-Achsen-Etiketten sind an Linien ausgerichtet, aber nicht an Balken

enter image description here

mit roten Linien I markiert, wo die Etiketten sein sollte.

Ich habe jsFiddle: http://jsfiddle.net/n2hfN/

Dank!

+1

Sie könnten stattdessen die Linie plus Balkendiagramm verwenden. –

+0

Danke für die Antwort. Aber in 'nv.models.linePlusBarChart' kann ich Attribut' bar' 'true | false' verwenden, ich habe keine Optionen mehr für verschiedene Diagramme. – Orbitum

+0

Zusätzlich muss ich positionieren - auf welcher Achse Linien stehen und auf welchen Balken. 'multiChart' erlaubt das. – Orbitum

Antwort

9

Wie @Miichi erwähnt, dies ein Fehler in nvd3 ist ...

Ich bin überrascht, dass sie eine ToDo „herauszufinden, warum der Wert verschoben zu werden scheint“, weil es ziemlich offensichtlich ist ... Die Balken verwenden eine Ordinalskala mit .rangeBands(), und die Linie verwendet eine lineare Skala, und die zwei Maßstäbe werden niemals so hergestellt, dass sie sich aufeinander beziehen, außer dass sie dieselben Endpunkte teilen.

Eine Lösung wäre, die Ordinalskala von den Balken zu nehmen und sie einfach um die Hälfte der Balkenbreite anzupassen, um die x-Skala der Linie zu bilden. Das würde die Linienpunkte in die Mitte der Balken bringen. Ich stelle mir vor, dass etwas Ähnliches in der nv.models.linePlusBarChart, die @LarsKotthoff erwähnt, getan wird.

Grundsätzlich Ihre Linie der x-Skala würde wie folgt aussehen:

var xScaleLine = function(d) { 
    var offset = xScaleBars.rangeBand()/2; 
    return xScaleBars(d) + offset; 
}; 

... wo xScaleBars die x-Skala für den Stegabschnitt des Diagramms verwendet wird.

Durch das Durchkämmen des Quellcodes für nvd3 scheint es, dass diese Skala als chart.bars1.scale() zugänglich ist.

Vielleicht eines Tages werden die Autoren von nvd3 entscheiden, dass ihre Kluft einer Bibliothek einige Dokumentation verdient. Für jetzt kann ich Ihnen die Art der Sache zeigen, die das Problem lösen würde, indem Sie ein kundenspezifisches Diagramm machen und zeigen, wie die zwei Skalen sich beziehen würden.

Zuerst werde ich Ihre Daten verwenden, aber die Linien- und Balkendaten in zwei Arrays trennen:

var barData = [ 
    {"x":0,"y":6500}, 
    {"x":1,"y":8600}, 
    {"x":2,"y":17200}, 
    {"x":3,"y":15597}, 
    {"x":4,"y":8600}, 
    {"x":5,"y":814} 
]; 

var lineData = [ 
    {"x":0,"y":2}, 
    {"x":1,"y":2}, 
    {"x":2,"y":4}, 
    {"x":3,"y":6}, 
    {"x":4,"y":2}, 
    {"x":5,"y":5} 
]; 

Dann die Waage für die Stäbe aufgebaut. Für die x-Skala verwende ich eine ordinale Skala und rangeRoundBands mit dem Standard-Gruppenabstand für nvd3 multiBar, die 0,1 ist. Für die y-Skala verwende ich eine reguläre lineare Skala, die .nice() verwendet, so dass die Skala nicht auf einem unangenehmen Wert endet, wie es standardmäßig in nvd3 ist. Wenn Sie über dem größten Wert Platz haben, erhalten Sie einen Kontext, der "schön" ist, wenn Sie versuchen, ein Diagramm zu interpretieren.

var xScaleBars = d3.scale.ordinal() 
    .domain(d3.range(barData.length)) 
    .rangeRoundBands([0, w], 0.1); 

var yScaleBars = d3.scale.linear() 
    .domain([0, d3.max(barData, function(d) {return d.y;})]) 
    .range([h, 0]) 
    .nice(10); 

Jetzt hier ist der wichtige Teil. Für die x-Skala Linie, keinen separaten Maßstab machen, aber nur es macht eine Funktion der x-Skala Bars:

var xScaleLine = function(d) { 
    var offset = xScaleBars.rangeBand()/2; 
    return xScaleBars(d) + offset; 
}; 

Hier ist das komplette Beispiel als JSBin.Ich habe versucht, die wichtigsten Abschnitte mit Kommentaren zu dokumentieren, so dass es einfach ist, der Gesamtlogik zu folgen. Wenn Sie aus dem nvd3-Quellcode genau herausfinden können, wie jedes der Elemente des multiChart aufgerufen wird und wie Sie die einzelnen Maßstäbe der Bestandteile einstellen, dann können Sie vielleicht einfach den neuen Maßstab einstecken.

Mein Gefühl ist, dass Sie einen ziemlich guten Griff haben müssen, wie d3 arbeitet, um etwas Nützliches mit nvd3 zu tun, und wenn Sie es anpassen möchten, sind Sie wahrscheinlich besser dran nur Ihre eigenen Diagramm rollen. Auf diese Weise haben Sie vollständige Kenntnisse und Kontrolle darüber, was die Elementklassen und Variablennamen der Teile Ihres Diagramms sind, und können mit ihnen alles machen, was Sie wollen. Wenn nvd3 jemals die richtige Dokumentation bekommt, wird dies vielleicht eine einfache Lösung. Viel Glück, und ich hoffe, das hilft dir wenigstens beim Einstieg.

+0

Danke! Ich sehe, dass dein Beispiel funktioniert und akzeptiere deine Antwort als die beste (vielen Dank für solch eine gründliche Recherche). Ich werde es wenig später versuchen und Ergebnisse berichten. – Orbitum

+0

Sie bieten an, NVD3-Diagramm neu zu schreiben, aber in Ihrem Beispiel arbeitet mit einfachen Daten. Ich aktualisiere Geige http://jsfiddle.net/n2hfN/28/ mit komplexeren Daten und verstehe nicht, wie gruppierte Bars und Multiline-Möglichkeit zu verwalten. – Orbitum

+0

Ich würde gerne mit einem anderen Szenario helfen, aber die Kommentare sind nicht der Ort für diese Diskussion. Dies war eine spezifische Frage, auf die ich eine spezifische Antwort gab. Wenn Sie eine neue Frage zu Ihrer neuen Frage stellen, können wir sie dort diskutieren. Eine Sache, die ich sagen werde ist, dass es so aussieht, als ob das MultiChart-Modell die Daten wie ich zerlegt, aber sie tun es mit Filtern. [** Hier sind die relevanten Zeilen im Quelltext **] (https://github.com/novus/nvd3/blob/master/src/models/multiChart.js#L70-L75) – jshanley