Czy istnieje prosty sposób wyrównania etykiet tekstowych między znacznikami?d3.js: Wyrównaj etykiety tekstowe między znacznikami na osi
Oto moja oś czasu z etykietami powyżej kleszczy:
Chciałbym umieścić te etykiety jak tutaj:
Czy istnieje prosty sposób wyrównania etykiet tekstowych między znacznikami?d3.js: Wyrównaj etykiety tekstowe między znacznikami na osi
Oto moja oś czasu z etykietami powyżej kleszczy:
Chciałbym umieścić te etykiety jak tutaj:
skończyło się z jednym z Lars Kotthoff's advices.
Za każdym razem, gdy I call(axis)
również dostosowuję etykiety tekstowe.
Tutaj jest uproszczony kod:
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);
}
Aktualizacja:
BTW, tutaj jest demo kalendarz które skończyło się: http://bl.ocks.org/oluckyman/6199145
Nie ma prostego (czyli wbudowane) sposób robienia tego, ale nadal możesz to osiągnąć. Istnieje kilka opcji. Najprostszym jest użycie tickFormat
function do określenia formatu z odpowiednią liczbą spacji przed/po liczbach. Musiałoby to jednak zostać dostrojone ręcznie dla każdej aplikacji.
Można również wybrać elementy etykiety po ich narysowaniu i dodać odpowiedni atrybut transform
, który odpowiednio je przesuwa. Ponownie, to musiałoby być ręcznie dostrojone.
Twoja trzecia opcja to dwie różne osie, jedna dla kleszczy i jedna dla etykiet. Chodzi o to, że oś, która dostarcza kleszcze, nie ma etykiet, a druga nie ma kleszczy. Musiałbyś odpowiednio ustawić wartości znaczników, ale przynajmniej nie musiałbyś zgadywać właściwego przesunięcia.
Możesz to zrobić, używając axis.tickSize(major[[,minor],end])
i .tickSubdivide()
. Twoje tyknięcia ustawiają się w linii z większymi kleszczami, ale jeśli ustawisz wysokość tych tyknięć na 0 i ustawisz wysokość dla mniejszych tyknięć i określisz, że istnieje jeden mniejszy tyk między każdą parą dużych tyknięć, to skończysz wraz z etykietami zaznaczającymi między kleszczami. Twój kod będzie wyglądał następująco:
var myAxis = d3.svg.axis()
.ticks(15)
.tickSubdivide(1)
.tickSize(0, 6, 0);
Pamiętaj, że musisz wyraźnie ustawić rozmiar końcowy. Jeśli tylko zapewniają dwie liczby, będą interpretowane jako major
i end
i minor
domyślnie 0.
Oto fiddle.
Fajny hack! Ale z powodu tego włamania dane zostaną przesunięte, a zamiast "3" dostaniesz "3.5". Zobacz obrazek: http://i.stack.imgur.com/OmfDN.png – oluckyman
Ostrzegam przed umieszczaniem etykiety w innym miejscu niż tyknięcie reprezentujące tę wartość. Jako użytkownik, założyłbym, że zaznaczenie między dwiema etykietami reprezentuje wartość między etykietami. Posiadanie go reprezentuje numer po jednej stronie lub po drugiej tworzy niejednoznaczność. Ponadto, d3 nie ma sposobu, aby to zrobić. – ckersch
Istnieje specjalny przypadek: kalendarz. W terminach kalendarzowych i dniach roboczych są umieszczane między kleszczami. – oluckyman
I często to zrobić poprzez układanie wiele osi, każda z niestandardowym .tickFormat()
.
Jeśli mam umieszczania etykiet między datami, ja często zrobić coś takiego:
@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)
będę też utworzyć osobną oś bez etykiet w ogóle, a niezerowe .tickSize()
faktycznie rysować tyknięcia, ale ten blok powyżej pozycji etykiety daty w środku "kolumny".
Wow, dlaczego cała nienawiść do tej odpowiedzi? To solidna technika. –
Już kilka dobrych odpowiedzi, ale po prostu dodać jeszcze jeden. Zwróć uwagę na użycie text-anchor
.
Taki sam pomysł: Po zakończeniu rozmowy wybierz tekst, zmień pozycję.
.call(xAxis)
.selectAll(".tick text")
.style("text-anchor", "start")
.attr("x", axisTextAdjust)
Dokładnie to, czego potrzebowałem, dzięki – James
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)"});
pierwszy nie pomoże w moim przypadku, ponieważ oś jest zoomable. – oluckyman
We wszystkich tych przypadkach konieczne jest zresetowanie odpowiednich parametrów po powiększeniu. –