Я создал дерево в D3.js на основе дерева узлов связи Майка Бостока. Проблема, с которой я сталкиваюсь и которую я также вижу в дереве Майка, заключается в том, что текстовая метка перекрывает/не перекрывает узлы круга, когда места недостаточно, а не расширяет ссылки, чтобы оставить немного места.
Мне как новому пользователю не разрешено загружать изображения, поэтому вот ссылка на дерево Майка, где вы можете видеть метки предыдущих узлов, перекрывающих следующие узлы.
Я пробовал разные вещи, чтобы решить проблему, определяя длину текста в пикселях с помощью:
d3.select('.nodeText').node().getComputedTextLength();
Однако это работает только после рендеринга страницы, когда мне нужна длина самого длинного текстового элемента перед рендерингом.
Получение самого длинного текстового элемента перед визуализацией с помощью:
nodes = tree.nodes(root).reverse();
var longest = nodes.reduce(function (a, b) {
return a.label.length > b.label.length ? a : b;
});
node = vis.selectAll('g.node').data(nodes, function(d, i){
return d.id || (d.id = ++i);
});
nodes.forEach(function(d) {
d.y = (longest.label.length + 200);
});
возвращает только длину строки, при использовании
d.y = (d.depth * 200);
делает каждую ссылку статической длины и не изменяет размер так красиво, когда открываются или закрываются новые узлы.
Есть ли способ избежать этого дублирования? Если да, то как лучше всего это сделать и сохранить динамическую структуру дерева?
Есть 3 возможных решения, которые я могу придумать, но они не так просты:
- Определение длины метки и использование многоточия там, где она выходит за пределы дочерних узлов. (что сделало бы этикетки менее читаемыми)
- динамическое масштабирование макета, определяя длину метки и сообщая ссылкам о соответствующей корректировке. (что было бы лучше, но кажется действительно сложным
- масштабируйте элемент svg и используйте полосу прокрутки, когда метки начинают переполняться. (не уверен, что это возможно, поскольку я работал с предположением, что SVG должен иметь заданную высоту и ширину).