webentwicklung-frage-antwort-db.com.de

d3.js: Textbeschriftungen zwischen Häkchen auf der Achse ausrichten

Gibt es eine einfache Möglichkeit, Textbeschriftungen zwischen Zecken auszurichten? 

Hier ist meine Zeitachse mit Beschriftungen über den Häkchen:
enter image description here

Ich möchte diese Etiketten gerne hier platzieren:
enter image description here

34
oluckyman

Am Ende hatte ich einen der Lars Kotthoffs Ratschläge

Jedes Mal, wenn ich call(axis) benutze, passe ich auch Beschriftungen an.
Hier ist vereinfachter Code:

function renderAxis() {
    axisContainer
        .transition().duration(300)
        .call(axis)                  // draw the standart d3 axis
        .call(adjustTextLabels);     // adjusts text labels on the axis 
}

function adjustTextLabels(selection) {
    selection.selectAll('.major text')
        .attr('transform', 'translate(' + daysToPixels(1) / 2 + ',0)');
}

// calculate the width of the days in the timeScale
function daysToPixels(days, timeScale) {
    var d1 = new Date();
    timeScale || (timeScale = Global.timeScale);
    return timeScale(d3.time.day.offset(d1, days)) - timeScale(d1);
}

Update:
Übrigens, hier ist eine calendar Demo, die ich am Ende beendet habe: http://bl.ocks.org/oluckyman/6199145

enter image description here

46
oluckyman

Es gibt keine einfache (d. H. Eingebaute) Möglichkeit, dies zu tun, aber Sie können es trotzdem erreichen. Es gibt einige Möglichkeiten. Am einfachsten ist es wahrscheinlich, die Funktion tickFormat zu verwenden, um ein Format mit einer geeigneten Anzahl von Leerzeichen vor/hinter den Zahlen anzugeben. Dies müsste jedoch für jede Anwendung manuell abgestimmt werden.

Alternativ können Sie die Beschriftungselemente auswählen, nachdem sie gezeichnet wurden, und ein geeignetes transform-Attribut hinzufügen, das sie entsprechend verschiebt. Dies müsste wiederum manuell abgestimmt werden.

Ihre dritte Option besteht darin, zwei verschiedene Achsen zu haben, eine für die Hilfsstriche und eine für die Beschriftungen. Die Idee ist, dass die Achse, die die Ticks bereitstellt, keine Labels und die andere keine Ticks hat. Sie müssten die Tick-Werte entsprechend einstellen, aber Sie müssten zumindest nicht den richtigen Offset erraten.

5
Lars Kotthoff

Sie können dies tun, indem Sie axis.tickSize(major[[,minor],end]) und .tickSubdivide() verwenden. Ihre Häkchen sind so eingestellt, dass sie mit den großen Häkchen übereinstimmen. Wenn Sie jedoch die Höhe dieser Häkchen auf 0 setzen und eine Höhe für kleinere Häkchen festlegen und angeben, dass zwischen jedem Paar großer Häkchen ein kleiner Häkchen gesetzt ist, werden Sie enden mit Tick-Labels zwischen Ihren Ticks Ihr Code würde so aussehen:

var myAxis = d3.svg.axis()
    .ticks(15)
    .tickSubdivide(1)
    .tickSize(0, 6, 0);

Beachten Sie, dass Sie explizit eine Endgröße festlegen müssen. Wenn Sie nur zwei Zahlen angeben, werden diese als major und end interpretiert, und minor wird standardmäßig auf 0 gesetzt.

Hier ist eine Geige.

2
ckersch

Schon ein paar gute Antworten, nur um noch eine hinzuzufügen. Beachten Sie die Verwendung von text-anchor

Gleiche Idee: Wählen Sie nach Ihrem Anruf den Text aus und positionieren Sie ihn neu.

.call(xAxis)                
.selectAll(".tick text")
.style("text-anchor", "start")
.attr("x", axisTextAdjust)

Ich mache das oft durch Stapeln mehrerer Achsen, jede mit einem benutzerdefinierten .tickFormat().

Wenn ich Etiketten zwischen zwei Daten platziere, mache ich oft Folgendes:

@timeDaysAxisLabels = d3.svg.axis()
    .scale(@timescale)
    .orient('bottom')
    .ticks(d3.time.hour.utc, 12)  # I want ticks at noon, easiest to just get them ever 12 hours
    .tickFormat((d) =>
        # only draw labels at noon, between the date boundaries
        if d.getUTCHours() == 12
            # draw the label!
            formatter = d3.time.format.utc('%a %d %b')  # "Mon 12 Apr"
            return formatter(d)
        else
            # not noon, don't draw anything
            return null)
    .tickSize(0)
    .tickPadding(30)

Ich werde auch eine separate Achse ohne Beschriftungen erstellen und eine .tickSize() ungleich Null, um Ticks zu zeichnen, aber dieser Block oberhalb positioniert Datumsbeschriftungen in der Mitte der "Spalte".

0
Idan Gazit

Vielleicht möchten Sie D3FC verwenden, das einen Drop-In-Ersatz für die D3-Achsenkomponente bietet, die diese Funktion unterstützt.

Hier ist ein Beispiel, das die D3-Achse d3.axisBottom Durch das D3FC-Äquivalent fc.axisBottom Ersetzt:

const axis = fc.axisBottom(linear)
  .tickCenterLabel(true);

Das tickCenterLabel zentriert die Achsenbeschriftungen wie gewünscht.

So sieht die Achse mit tickCenterLabel = false Aus:

enter image description here

Und hier mit dem tickCenterLabel = true:

enter image description here

Vollständige Offenlegung - Ich bin ein Betreuer und ein Mitwirkender an D3FC

0
ColinE
        svg.append("g")
          .attr("class", "axis axis-years")
          .attr("transform", "translate(0," + (height + 1) + ")")
          .call(xAxis)
        .selectAll("text")

     .attr("x", "-1.8em")
     .attr("y", ".00em")
     .attr("transform", function (d) {
         return "rotate(-90)"});
0
VINOTH KUMAR