Как я могу динамически изменить размер SVG-прямоугольника в зависимости от ширины текста? - PullRequest
0 голосов
/ 17 декабря 2018

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

Вот создание прямоугольников с D3.js (с использованием фиксированной ширины и высотызначения):

var rects = nodeEnter.append("rect")
    .attr("width", rectW)
    .attr("height", rectH);

, за которым следует текстовый элемент:

var nodeText = nodeEnter.append("text")
    .attr("class", "node-text")
    .attr("y", rectH / 2)
    .attr("dy", ".35em")
    .text(function (d) {
        return d.data.name;
    });
nodeText // The bounding box is valid not before the node addition happened actually.
    .attr("x", function (d) {
        return (rectW - this.getBBox().width) / 2;
    });

Как видите, в настоящее время я центрирую текст в доступном пространстве.Затем я попытался установить ширину ректов на основе их текста, но я никогда не получал одновременно и элемент rect, и текстовый HTML-элемент (для getBBox ()) одновременно.Вот одна из моих попыток:

rects.attr("width",
        d => this.getBBox().width + 20
    );

, но, очевидно, this неверно, поскольку относится к rects, а не к тексту.

Какой здесь правильный подход?

Ответы [ 2 ]

0 голосов
/ 17 декабря 2018

Решение довольно простое, если вспомнить, что привязка this в вызове attr() относится к связанному элементу HTML (SVG):

rects.attr("width",
    d => this.parentNode.childNodes[1].getComputedTextLength() + 20;
);

Прямоугольник - это первый элемент всписок элементов SVG, составляющих узел для отображения.Текст для этого узла имеет индекс 1 (как следует из вызовов append).

0 голосов
/ 17 декабря 2018

Я бы использовал getComputedTextLength для измерения текста.Я не знаю, есть ли для этого эквивалент в D3.js. Мой ответ использует обычный javascript и предполагает, что прямоугольник и текстовый центр - {x: 50, y: 25}, а вы используете text{dominant-baseline:middle;text-anchor:middle;}

let text_length = txt.getComputedTextLength();

rct.setAttributeNS(null,"width",text_length )
rct.setAttributeNS(null,"x",(50 - text_length/2) )
svg{border:1px solid}
text{dominant-baseline:middle;text-anchor:middle;}
<svg viewBox="0 0 100 50">
  <rect x="25" y="12.5" width="50" height="25" stroke="black" fill="none" id="rct" />
  <text x="50" y="25" id="txt">Test text</text>
</svg>

В качестве альтернативы вместо txt.getComputedTextLength() вы можете использовать txt.textLength.baseVal.value

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...