Лучший способ уместить текст переменного размера в полукруг в d3.js?

В настоящее время я работаю над визуализацией в d3.js с целью визуализировать сходство данных. Я хочу сравнить свои данные в кругах, создав два полукруга для каждого узла и поместив данные сравнения в эти полукруги. Мои данные состоят из строк (каждый полукруг получает одно предложение).

Мой нынешний подход заключается в следующем:
сначала я создаю необходимые данные узла, используя pack-layout.

var bubble = d3.pack().size([SVG_WIDTH,SVG_HEIGHT]).padding(CIRCLE_PADDING),
    root = d3.hierarchy({children: COMPARISON_DATA}).sum(function(d){  return d.children ? 0 : d[2]});

var nodeData = bubble(root).children;

d[2] - максимальная длина строки из двух предложений, помещаемых в полукруги, и, таким образом, определяет радиус кругов.

Затем я перебираю каждый узел и создаю соответствующие полукруги. Я удалил все части кода, которые не имеют отношения к моему вопросу.

 nodeData.forEach(function (data, index) {
    //upperCircleGroup simply adds a small y-translate, so that the semicircles have a margin 
    var gUpper = upperCircleGroup.append("g");
    var gLower = lowerCircleGroup.append("g");


    var lowerCircle = gLower.append('path')
        .attr('d', d3.arc()({
            innerRadius: 0,
            outerRadius: data.r,
            startAngle: Math.PI / 2,
            endAngle: 3 / 2 * Math.PI
        }))
        .attr('transform', `translate(${data.x},${data.y})`)


      var upperCircle = gUpper.append('path')
        .attr('d', d3.arc()({
            innerRadius: 0,
            outerRadius: data.r,
            startAngle: 1 / 2 * Math.PI,
            endAngle: - 1 / 2 * Math.PI
        }))
        .attr('transform', `translate(${data.x},${data.y})`)

    var upperText = gUpper
        .append("foreignObject")
        .attr("width", () => {return data.r*Math.sqrt(2)})
        .attr("height", () => {return data.r*(Math.sqrt(2)/2)})
        .attr('transform', `translate(${data.x - (data.r / Math.sqrt(2))},${data.y - (data.r/Math.sqrt(2)) })`)
        .text(() => {return data.data[0]})

    var lowerText = gLower
        .append("foreignObject")
        .attr("width", () => {return data.r*Math.sqrt(2)})
        .attr("height", () => {return data.r*(Math.sqrt(2)/2)})
        .attr('transform', `translate(${data.x - (data.r / Math.sqrt(2))},${data.y  })`)
        .text(() => {return data.data[1]})
});

Как видите, я рисую полукруги с помощью дуги d3. Здесь возникает мой вопрос. У меня возникли проблемы с размещением моего текстового содержимого внутри дуги, поэтому после некоторого поиска я выбрал это решение, чтобы поместить div внутри моих полукругов, которые затем получают текст. Операции sqrt(2) используются для размещения квадрата в полукруге.

Моя проблема с этим решением заключается в том, что иногда предложение просто не помещается в div, и часть содержимого теряется. Есть ли способ вычислить необходимый размер шрифта строки, чтобы он соответствовал div заданного размера? Если бы это было возможно, я мог бы просто вычислить соответствующий размер шрифта и добавить параметр масштабирования к визуализации. Кроме того, если есть более эффективные способы достичь того, что я пытаюсь сделать, я также был бы рад получить некоторые отзывы от вас, ребята, потому что я полный новичок, когда дело доходит до использования d3.

1 ответ

Сделать текст отзывчивым на элемент сложно, но CSS-Tricks сделали отличную статью о различных способах подхода к этому...

https://css-tricks.com/fitting-text-to-a-container/

Другие вопросы по тегам