2014-02-06 3 views
10

Вот JSFiddle: http://jsfiddle.net/8p2yc/ (слегка измененный пример здесь: http://bl.ocks.org/mbostock/3883245)Как установить метки ярлыка переменной длины на линейной диаграмме D3?

Как вы можете видеть в JSFiddle тик метки вдоль оси у не помещаются в 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

Спасибо!

ответ

12

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

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 + ")"); 

Полный пример here.

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

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(); 

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

+1

Звучит неплохо, только одна потенциальная проблема, я думаю. Наибольшее число не обязательно является самым длинным с точки зрения количества символов. например 1 и 0,22323332. Что было бы лучшим способом узнать «длинный» номер после форматирования? thx v much – vrepsys

+0

Хорошо, я уточню ответ. –

+0

Я думаю, что может возникнуть проблема, когда правая сторона графика будет отрезана, если правое поле станет большим.Должно быть легко исправить, если отрегулировать ширину в зависимости от рассчитанной maxWidth. Не стесняйтесь редактировать ответ, он примет в любом случае. thx – vrepsys

0

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

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

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

Смежные вопросы