Javascript SVG:使用 getComputedTextLength 来包装文本

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7046986/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 00:35:49  来源:igfitidea点击:

SVG: using getComputedTextLength to wrap text

javascriptsvg

提问by EML

I'm trying to wrap text by building up a text string, and using getComputedTextLengthto find out when the text goes beyond the allowed width. However, I can't find a simple way to incrementally build up the text which will work with getComputedTextLength.

我试图通过构建文本字符串来包装文本,并使用它getComputedTextLength来找出文本何时超出允许的宽度。但是,我找不到一种简单的方法来逐步构建适用于getComputedTextLength.

The general idea is:

总体思路是:

  str = svgDocument.createTextNode(myText[word]); // first word on new line
  word++;
  obj = text.cloneNode(true);                     // new text element for this line
  obj.appendChild(str);
  svgDocument.documentElement.appendChild(obj);   // reqd for getComputedTextLength?
  for( ; word < myText.length; word++) {
     next_width = obj.getComputedTextLength();    // get current line width
     if(next_width >= extent)
        break;
     str += " ";                                  // add next word to the line
     str += myText[word];
     ...
  }

Can anyone tell me how to get this to work? Presumably stris copied rather than referenced in obj, but I've also tried putting obj.removeChild(str)and obj.appendChild(str)in the loop, but the appendChildcrashes. I've also tried various combinations of moving around the documentElement.appendChild, and removing objand re-appending it, and so on.

谁能告诉我如何让这个工作?大概str是在 中复制而不是引用obj,但我也尝试将obj.removeChild(str)obj.appendChild(str)放入循环中,但appendChild崩溃了。我还尝试了在 周围移动documentElement.appendChild、删除obj和重新附加它的各种组合,等等。

回答by Peter Collingridge

This should work:

这应该有效:

    var svgNS = "http://www.w3.org/2000/svg";
    var width = 200;

    function init(evt)
    {
        if ( window.svgDocument == null ) {
            svgDocument = evt.target.ownerDocument;
        }
        create_multiline("Whatever text you want here.");
    }

    function create_multiline(text) {
        var words = text.split(' ');                        
        var text_element = svgDocument.getElementById('multiline-text');
        var tspan_element = document.createElementNS(svgNS, "tspan");   // Create first tspan element
        var text_node = svgDocument.createTextNode(words[0]);           // Create text in tspan element

        tspan_element.appendChild(text_node);                           // Add tspan element to DOM
        text_element.appendChild(tspan_element);                        // Add text to tspan element

        for(var i=1; i<words.length; i++)
        {
            var len = tspan_element.firstChild.data.length;             // Find number of letters in string
            tspan_element.firstChild.data += " " + words[i];            // Add next word

            if (tspan_element.getComputedTextLength() > width)
            {
                tspan_element.firstChild.data = tspan_element.firstChild.data.slice(0, len);    // Remove added word

                var tspan_element = document.createElementNS(svgNS, "tspan");       // Create new tspan element
                tspan_element.setAttributeNS(null, "x", 10);
                tspan_element.setAttributeNS(null, "dy", 18);
                text_node = svgDocument.createTextNode(words[i]);
                tspan_element.appendChild(text_node);
                text_element.appendChild(tspan_element);
            }
        }


    }
]]>
</script>

<text x="10" y="50" id="multiline-text"> </text>

It works by adding tspan elements to the text element and then adding text to each of them.

它的工作原理是将 tspan 元素添加到文本元素,然后向每个元素添加文本。

The result is something like:

结果是这样的:

<text>
  <tspan>Whatever text</tspan>
  <tspan>you want here.</tspan>
</text>

In order for getComputerTextLength to work, you need to create the tspan (or text) element first and make sure it is in DOM. Also note that in order to add text to a tspan element, you need to use createTextNode() and append the result.

为了让 getComputerTextLength 起作用,您需要先创建 tspan(或文本)元素并确保它在 DOM 中。另请注意,为了向 tspan 元素添加文本,您需要使用 createTextNode() 并附加结果。

回答by user2846569

a wrapper function for overflowing text:

用于溢出文本的包装函数:

    function wrap() {
        var self = d3.select(this),
            textLength = self.node().getComputedTextLength(),
            text = self.text();
        while (textLength > (width - 2 * padding) && text.length > 0) {
            text = text.slice(0, -1);
            self.text(text + '...');
            textLength = self.node().getComputedTextLength();
        }
    } 

usage:

用法:

text.append('tspan').text(function(d) { return d.name; }).each(wrap);