【问题标题】:SVG: using getComputedTextLength to wrap textSVG:使用 getComputedTextLength 包装文本
【发布时间】:2011-10-26 04:40:36
【问题描述】:

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

大体思路是:

  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];
     ...
  }

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

【问题讨论】:

    标签: javascript svg


    【解决方案1】:

    这应该有效:

        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>
    

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

    结果是这样的:

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

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

    【讨论】:

    • 嗨彼得 - 感谢您的代码。我今天在看我的原始代码,发现我的基本问题是误解了如何在文本节点中增长文本。我得到了使用 appendChild 的基本包装,但你的 tspan 东西看起来不错 - 我会检查一下。谢谢-Al
    • 酷 - tspan 很有用,因为它意味着您可以一次选择多行文本。
    • 7 年后仍然有帮助,我想这有好有坏!
    【解决方案2】:

    溢出文本的包装函数:

        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();
            }
        } 
    

    用法:

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

    【讨论】:

    • OP 代表什么?
    • 原始海报。 D3 代表什么? :)
    • D3 是用于操作 SVG 的 JavaScript 库。 @RobertLongson,OP 并不是唯一一个阅读此书的人。还有其他人需要解决这个问题,甚至更多,有些人像我一样使用 D3。干杯!
    • 普通的 JS/DOM 问题仍然可以用 jQuery sn-ps 回答,但我看到用 d3.js 回答的第一个问题受到批评。 user2846569 的回答很有用,因为 1) 对该主题感兴趣的 d3 用户可能会发现他的回答很有用,如果他们先找到这个答案,2) Core d3.js 可以被称为“类固醇上的 SVG jQuery”——有一个d3 用户和需要在 SVG 中截断文本的用户之间有很大的重叠; 3) OP 或读者可能会了解到,OP 的问题中相当长的、命令式的、纠缠不清的代码也可以使用更具声明性的 d3 库来完成。
    • 似乎这要求 SVG 是可见的:例如,如果它被带有 display:none; 的东西包裹,那么 getComputedTextLength() 将返回 0。这是我的浏览器的行为。谁能确认一下?
    猜你喜欢
    • 2017-08-26
    • 1970-01-01
    • 2012-06-10
    • 2015-12-24
    • 1970-01-01
    • 1970-01-01
    • 2018-03-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多