Existe-t-il un moyen simple d’aligner les étiquettes de texte entre les ticks?
Voici mon axe temporel avec des étiquettes au-dessus des ticks:
Je voudrais placer ces étiquettes comme ici:
Je me suis retrouvé avec l'un des conseils de Lars Kotthoff .
Chaque fois que je call(axis)
, je modifie également les étiquettes de texte.
Voici le code simplifié:
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);
}
Mettre à jour:
BTW, voici une démo du calendrier qui m’a fini: http://bl.ocks.org/oluckyman/6199145
Il n’existe pas de moyen facile (c’est-à-dire intégré) de le faire, mais vous pouvez quand même y parvenir. Il y a quelques options. Le plus simple consiste probablement à utiliser la fonction tickFormat
pour spécifier un format avec un nombre approprié d’espaces devant/après les nombres. Cela devrait cependant être réglé manuellement pour chaque application.
Vous pouvez également sélectionner les éléments d'étiquette une fois qu'ils ont été dessinés et ajouter un attribut transform
approprié qui les décale en conséquence. Encore une fois, cela devrait être réglé à la main.
Votre troisième option consiste à avoir deux axes différents, un pour les graduations et un pour les libellés. L'idée est que l'axe qui fournit les ticks n'a pas de libellé et l'autre pas de ticks. Vous devez définir les valeurs de ticks de manière appropriée, mais au moins vous n’auriez pas à deviner le bon décalage.
Vous pouvez le faire en utilisant axis.tickSize(major[[,minor],end])
et .tickSubdivide()
. Vos ticks sont configurés pour s'aligner sur les ticks principaux, mais si vous définissez la hauteur de ces ticks sur 0, définissez une hauteur pour les ticks mineurs et spécifiez qu'il existe un tick parallèle entre chaque paire de ticks majeurs, avec des étiquettes de tiques entre vos tiques. Votre code ressemblerait à ceci:
var myAxis = d3.svg.axis()
.ticks(15)
.tickSubdivide(1)
.tickSize(0, 6, 0);
Notez que vous devez définir explicitement une taille de fin. Si vous ne fournissez que deux chiffres, ils seront interprétés comme étant major
et end
et minor
seront par défaut à 0.
Voici un violon.
Déjà quelques bonnes réponses mais juste pour en ajouter une de plus. Notez l'utilisation de text-anchor
.
Même idée: après votre appel, sélectionnez le texte, repositionnez-le.
.call(xAxis)
.selectAll(".tick text")
.style("text-anchor", "start")
.attr("x", axisTextAdjust)
Je le fais souvent en empilant plusieurs axes, chacun avec un .tickFormat()
personnalisé.
Si je place des étiquettes entre deux dates, je vais souvent faire quelque chose comme ceci:
@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)
Je vais aussi créer un axe séparé sans étiquette, et un .tickSize()
différent de zéro pour dessiner les ticks, mais ce bloc situé au-dessus positionne les étiquettes de date au centre de la "colonne".
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)"});