Существует несколько способов решения проблемы, связанной с наличием большого набора данных строк различной длины, который нам нужно поместить в коробки различных размеров.
Одним из способов было бы добавить обтравочный контур (clip-path
) к каждому элементу прямоугольника, но я думаю, что это будет слишком для такой визуализации, поэтому мы будем использовать другие средства.
Во-первых, вы можете добавить элемент заголовка к каждому g
; действие по умолчанию для большинства браузеров - показать всплывающую подсказку при наведении курсора на заголовок. Итак:
cells
.append('title')
.text(function(d){ return d.name });
Теперь давайте посмотрим на текстовые элементы. Установите font-family
и font-size
для текстовых узлов в вашей таблице стилей или заголовке документа, чтобы мы имели дело с предсказуемыми размерами текста.
.newcell text {
font-family: Arial, sans-serif;
font-size: 10px;
}
Я бы посоветовал немного сместить текст вниз, так как текущий код устанавливает базовую линию текста в вертикальном центре ячейки, которая является слишком высокой. Здесь я добавил смещение 0.35em
:
selection
.append("text")
.attr("x", function (d) {
return d.x + d.dx / 2;
})
.attr("y", function (d) {
return d.y + d.dy / 2;
})
.attr('dy', '.35em')
.attr("text-anchor", "middle")
.text(function (d) {
return d.children ? '' : d.name;
})
Мы можем фильтровать видимость текстовых узлов, изменяя непрозрачность (что означает, что мы можем легко переключать непрозрачность, чтобы показать / скрыть текст), используя
cells
.style('opacity', function(d){
// some function returning 0 or 1
});
Существуют различные методы, которые мы могли бы использовать, чтобы решить, показывать или скрывать текст. Можно было бы иметь минимальную ширину и минимальную высоту, которой должна быть ячейка для отображения текста в ней, например,
var minHeight = 12,
minWidth = 20;
cells
.style('opacity', function(d){
if ( d.dx <= minWidth || d.dy <= minHeight ) {
return 0
};
return 1;
});
Другим способом может быть вычисление приблизительной ширины слова и проверка его по ширине поля. Я нашел таблицу средней ширины символов для обычных шрифтов в https://www.math.utah.edu/~beebe/fonts/afm-widths.html,, поэтому мы можем угадать ширину слова, умножив длину слова на среднюю ширину символа (в точках), и умножив ее на размер шрифта ( в точках) и коэффициент пересчета для преобразования точек в пиксели
var pt_px = 0.75, // convert font size in pt into pixels
font_size = 10, // or whatever it is set to in the stylesheet
averageLetterWidth = 0.58344; // average character width for Arial
cells
.style('opacity', function(d){
if ( d.name.length * averageLetterWidth * pt_px * font_size >= d.dx ) {
return 0
}
return 1;
});
И еще один способ - сравнить размер ограничительной рамки текстового элемента с высотой и шириной ячейки:
cells
.style('opacity', function(d){
var bbox = this.getBBox();
if ( d.dx <= bbox.width || d.dy <= bbox.height ) {
return 0;
}
return 1;
});
Вы также можете убедиться, что между краем текста и рамкой есть отступы:
var h_pad = 2, // 2 pixels vertical padding
v_pad = 4; // 4 pixels of horizontal padding (2 px at each side)
cells
.style('opacity', function(d){
var bbox = this.getBBox();
if ( d.dx <= bbox.width + h_pad || d.dy <= bbox.height + v_pad ) {
return 0;
}
return 1;
});
Вы можете выбрать, какой из этих методов наиболее подходит для вашего варианта использования (или объединить их все!). Я собрал блок, который демонстрирует различные вычисления и их эффекты .