Как установить метки ярлыков переменной длины на линейной диаграмме D3?

Здесь JSFiddle: http://jsfiddle.net/8p2yc/ (Немного измененный пример отсюда: http://bl.ocks.org/mbostock/3883245)

Как вы можете видеть в ярлыках ярлыков JSFiddle вдоль оси y, они не вписываются в svg. Я знаю, что могу увеличить левый запас, но дело в том, что я не знаю, какие данные будут заблаговременно. Если я просто сделаю маржу очень большой, диаграмма будет выглядеть неудобно, если числа коротки в длине.

Есть ли способ прекомпилировать максимальную ширину метки при создании диаграммы для правильного задания поля? Или, может быть, есть совершенно другое решение?

var margin = {top: 20, right: 20, bottom: 30, left: 50},
    width = 400 - margin.left - margin.right,
    height = 200 - margin.top - margin.bottom;

var svg = d3.select("body").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

example chart

Спасибо!

Ответ 1

Вы можете сделать это, добавив текст для самой большой метки, измерив ее и сразу же удалив:

var maxLabel = d3.max(data, function(d) { return d.close; }),
    maxWidth;
svg.append("text").text(maxLabel)
   .each(function() { maxWidth = this.getBBox().width; })
   .remove();

Затем вы можете использовать эту ширину для перевода элемента g:

svg.attr("transform", "translate(" + Math.max(margin.left, maxWidth) + "," + margin.top + ")");

Полный пример здесь.

Изменить: получение максимальной длины фактических ярлыков немного связано с тем, что вы должны сгенерировать их (с правильным форматированием) и измерить их все. Это лучший способ сделать это, хотя вы измеряете то, что на самом деле отображается. Код похож:

var maxWidth = 0;
svg.selectAll("text.foo").data(y.ticks())
   .enter().append("text").text(function(d) { return y.tickFormat()(d); })
   .each(function(d) {
     maxWidth = Math.max(this.getBBox().width + yAxis.tickSize() + yAxis.tickPadding(), maxWidth);
   })
 .remove();

Я добавляю размер линии тика и отступы между тик-линией и меткой до ширины. Полный пример этого здесь.

Ответ 2

Проблема с курятиной и яйцом предотвращает ее предварительную вычисление надежно, предполагая, что вы хотите, чтобы ваши оси и график объединялись, чтобы заполнить фиксированное пространство, и ваши метки ярлыков будут генерироваться автоматически.

Проблема заключается в том, что метки меток и, следовательно, требуемое пространство зависят от масштаба. Например, временная шкала может включать более длинные месячные имена (например, "сентябрь" ) в коротком домене, но более короткие имена месяцев или только годы в длинном домене. Но масштаб, по крайней мере на противоположной оси, зависит от пространства, оставшегося для диапазона, которое зависит от оставшегося пространства после определения меток тика.

Во многих случаях минимальные и максимальные значения могут дать вам представление об самых ярких меток ярлыков, и вы можете использовать метод Lars. Например, если домен составляет от -50 до 10, любые метки меток между ними будут более узкими. Но это предполагает, что они целые числа! Кроме того, будьте осторожны с 'nice' scales; если ваше максимальное значение равно 8, D3 может попытаться сделать максимальную метку метки 10, которая является более широкой строкой.