Oznakowanie osi d3

94

Jak dodać etykiety tekstowe do osi w D3?

Na przykład mam prosty wykres liniowy z osiami x i y.

Na mojej osi X mam znaczniki od 1 do 10. Chcę, aby pod spodem pojawiło się słowo „dni”, aby ludzie wiedzieli, że oś x liczy dni.

Podobnie na osi Y cyfry 1-10 są zaznaczone jako kleszcze i chcę, aby słowa „zjedzone kanapki” pojawiały się z boku.

Czy jest na to prosty sposób?

user1474218
źródło

Odpowiedzi:

166

Etykiety osi nie są wbudowane w komponent osi D3 , ale możesz dodawać etykiety samodzielnie, po prostu dodając textelement SVG . Dobrym tego przykładem jest moje odtworzenie animowanego wykresu bąbelkowego Gapminder, The Wealth & Health of Nations . Etykieta osi X wygląda następująco:

svg.append("text")
    .attr("class", "x label")
    .attr("text-anchor", "end")
    .attr("x", width)
    .attr("y", height - 6)
    .text("income per capita, inflation-adjusted (dollars)");

I etykieta osi Y w ten sposób:

svg.append("text")
    .attr("class", "y label")
    .attr("text-anchor", "end")
    .attr("y", 6)
    .attr("dy", ".75em")
    .attr("transform", "rotate(-90)")
    .text("life expectancy (years)");

Możesz także użyć arkusza stylów, aby stylizować te etykiety według własnego uznania, razem ( .label) lub indywidualnie ( .x.label, .y.label).

mbostock
źródło
9
Odkryłem, że .attr("transform", "rotate(-90)")powoduje to rotację całego układu współrzędnych. Tak więc, jeśli pozycjonujesz za pomocą „x” i „y”, musisz zamienić pozycje z tego, czego się spodziewałem.
lubar
masz jakieś szczególne względy w przypadku wielu wykresów i chcesz mieć etykiety osi na wszystkich?
ted.strauss
31

W nowej wersji D3js (od wersji 3), kiedy tworzysz oś wykresu za pomocą d3.svg.axis()funkcji, masz dostęp do dwóch metod, które są wywoływane tickValuesi tickFormatsą wbudowane w funkcję, dzięki czemu możesz określić, do jakich wartości potrzebujesz tików iw jakim format, w jakim ma się pojawić tekst:

var formatAxis = d3.format("  0");
var axis = d3.svg.axis()
        .scale(xScale)
        .tickFormat(formatAxis)
        .ticks(3)
        .tickValues([100, 200, 300]) //specify an array here for values
        .orient("bottom");
ambodi
źródło
Niezłe wyjaśnienie, ale wygląda na to, że PO ma już kleszcze na swoich osiach.
Michael Scheper
1
OP? Przepraszam, nie rozumiem skrótu.
ambodi
Bez obaw. OP = „Oryginalny post” lub „Oryginalny plakat”. (Wyszukiwarki i urbandictionary.com to całkiem dobre referencje dla takich skrótów.)
Michael Scheper
13

Jeśli chcesz, aby etykieta osi Y znajdowała się na środku osi Y, tak jak ja:

  1. Obróć tekst o 90 stopni ze środkiem zakotwiczenia tekstu
  2. Przetłumacz tekst według jego środka
    • Pozycja x: aby zapobiec nakładaniu się etykiet znaczników osi Y ( -50)
    • pozycja y: aby dopasować środek osi y ( chartHeight / 2)

Przykład kodu:

var axisLabelX = -50;
var axisLabelY = chartHeight / 2;

chartArea
    .append('g')
    .attr('transform', 'translate(' + axisLabelX + ', ' + axisLabelY + ')')
    .append('text')
    .attr('text-anchor', 'middle')
    .attr('transform', 'rotate(-90)')
    .text('Y Axis Label')
    ;

Zapobiega to obracaniu się całego układu współrzędnych, o czym wspomniał Lubar powyżej.

Michael Clark
źródło
Jasne, dodałem więcej szczegółów, czy to lepiej?
Michael Clark
1
Tak! Głosowałem już za tym, ponieważ Twoja pierwotna odpowiedź postawiła mnie na właściwej drodze, ale tak jak jest teraz, przyszli czytelnicy nie będą musieli się nią zbytnio bawić, aby dowiedzieć się, co to wszystko oznacza. :-) Twoje zdrowie.
Michael Scheper
3

Jeśli pracujesz w d3.v4, zgodnie z sugestią, możesz użyć tej instancji, która oferuje wszystko, czego potrzebujesz.

Możesz po prostu zastąpić dane osi X swoimi „dniami”, ale pamiętaj, aby poprawnie przeanalizować wartości ciągów i nie stosować konkatenacji.

parseTime może równie dobrze załatwić sprawę dla dni skalowania z formatem daty?

d3.json("data.json", function(error, data) {
if (error) throw error;

data.forEach(function(d) {
  d.year = parseTime(d.year);
  d.value = +d.value;
});

x.domain(d3.extent(data, function(d) { return d.year; }));
y.domain([d3.min(data, function(d) { return d.value; }) / 1.005, d3.max(data, function(d) { return d.value; }) * 1.005]);

g.append("g")
    .attr("class", "axis axis--x")
    .attr("transform", "translate(0," + height + ")")
    .call(d3.axisBottom(x));


g.append("g")
    .attr("class", "axis axis--y")
    .call(d3.axisLeft(y).ticks(6).tickFormat(function(d) { return parseInt(d / 1000) + "k"; }))
  .append("text")
    .attr("class", "axis-title")
    .attr("transform", "rotate(-90)")
    .attr("y", 6)
    .attr("dy", ".71em")
    .style("text-anchor", "end")
    .attr("fill", "#5D6971")
    .text("Population)");

bawić się globalnym css / js

因特网 的 小熊
źródło
1

D3 zapewnia zestaw komponentów niskiego poziomu, których można użyć do tworzenia wykresów. Otrzymasz bloki konstrukcyjne, komponent osi, połączenie danych, wybór i SVG. Twoim zadaniem jest zebranie ich razem w celu utworzenia wykresu!

Jeśli potrzebujesz konwencjonalnego wykresu, tj. Pary osi, etykiet osi, tytułu wykresu i obszaru wykresu, dlaczego nie spojrzeć na d3fc ? jest to zestaw open source zawierający więcej komponentów D3 wysokiego poziomu. Zawiera komponent wykresu kartezjańskiego, który może być tym, czego potrzebujesz:

var chart = fc.chartSvgCartesian(
    d3.scaleLinear(),
    d3.scaleLinear()
  )
  .xLabel('Value')
  .yLabel('Sine / Cosine')
  .chartLabel('Sine and Cosine')
  .yDomain(yExtent(data))
  .xDomain(xExtent(data))
  .plotArea(multi);

// render
d3.select('#sine')
  .datum(data)
  .call(chart);

Pełniejszy przykład można zobaczyć tutaj: https://d3fc.io/examples/simple/index.html

ColinE
źródło
0
chart.xAxis.axisLabel('Label here');

lub

xAxis: {
   axisLabel: 'Label here'
},
Ravi Tej
źródło