SVG文本中的自动换行

til*_*lda 97 xml svg text word-wrap

我想<text>在SVG中显示一个自动换行到容器<rect>的内容,就像HTML文本填充<div>元素一样.有办法吗?我不想使用<tspan>s 来定位线条.

Tan*_*gui 81

文本换行不是SVG1.1的一部分,SVG1.1是当前实现的规范.您应该通过<foreignObject/>元素使用HTML .

<svg ...>

<switch>
<foreignObject x="20" y="90" width="150" height="200">
<p xmlns="http://www.w3.org/1999/xhtml">Text goes here</p>
</foreignObject>

<text x="20" y="20">Your SVG viewer cannot display html.</text>
</switch>

</svg>
Run Code Online (Sandbox Code Playgroud)

  • IE中也不支持<foreignObject /> (22认同)
  • 这是使用switch的错误方法,它需要使用svg规范中定义的某个功能串.在您的示例中永远不会使用回退.请参见http://www.w3.org/TR/SVG11/feature.html和http://www.w3.org/TR/SVG11/struct.html#SwitchElement. (5认同)
  • 但请注意,并非所有引擎都可以呈现foreignObjects.特别是,蜡染不. (3认同)

Eri*_*röm 67

这是另一种选择:

<svg ...>
  <switch>
    <g requiredFeatures="http://www.w3.org/Graphics/SVG/feature/1.2/#TextFlow">
      <textArea width="200" height="auto">
       Text goes here
      </textArea>
    </g>
    <foreignObject width="200" height="200" 
     requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
      <p xmlns="http://www.w3.org/1999/xhtml">Text goes here</p>
    </foreignObject>
    <text x="20" y="20">No automatic linewrapping.</text>
  </switch>
</svg>
Run Code Online (Sandbox Code Playgroud)

注意即使foreignObject可能被报告为支持该featurestring,也不能保证可以显示HTML,因为SVG 1.1规范不需要.目前,html-in-foreignobject支持没有featuretring.但是,它仍然在许多浏览器中得到支持,因此将来很可能需要它,可能还有相应的功能串.

请注意,SVG Tiny 1.2 中的'textArea'元素支持所有标准svg功能,例如高级填充等,并且您可以将宽度或高度指定为auto,这意味着文本可以在该方向上自由流动.ForeignObject充当剪切视口.

注意:虽然上面的示例是有效的SVG 1.1内容,但在SVG 2中,'requiredFeatures'属性已被删除,这意味着'switch'元素将尝试呈现第一个'g'元素,而不管是否支持SVG 1.2'textArea '元素.参见SVG2开关元件规格.

  • 应该注意的是textarea似乎不支持前进https://bugzilla.mozilla.org/show_bug.cgi?id=413360 (2认同)

use*_*765 13

textPath可能适用于某些情况.

<svg width="200" height="200"
    xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
 <defs>
  <!-- define lines for text lies on -->
  <path id="path1" d="M10,30 H190 M10,60 H190 M10,90 H190 M10,120 H190"></path>
 </defs>
 <use xlink:href="#path1" x="0" y="35" stroke="blue" stroke-width="1" />
 <text transform="translate(0,35)" fill="red" font-size="20">
  <textPath xlink:href="#path1">This is a long long long text ......</textPath>
 </text>
</svg>
Run Code Online (Sandbox Code Playgroud)

  • @Nilloc 不是每个人都使用英语,这种方法对于中文、日语或韩语完全没问题。 (6认同)
  • 只有在可以接受包装中间单词(而不是连字符)的情况下.我想不出艺术项目之外的很多案例都可以.[http://jsfiddle.net/nilloc/vL3zj/](http://jsfiddle.net/nilloc/vL3zj/) (3认同)

MSC*_*MSC 9

在@Mike Gledhill的代码的基础上,我进一步采取了更多参数.如果您有一个SVG RECT并希望文本包含在其中,这可能很方便:

function wraptorect(textnode, boxObject, padding, linePadding) {

    var x_pos = parseInt(boxObject.getAttribute('x')),
    y_pos = parseInt(boxObject.getAttribute('y')),
    boxwidth = parseInt(boxObject.getAttribute('width')),
    fz = parseInt(window.getComputedStyle(textnode)['font-size']);  // We use this to calculate dy for each TSPAN.

    var line_height = fz + linePadding;

// Clone the original text node to store and display the final wrapping text.

   var wrapping = textnode.cloneNode(false);        // False means any TSPANs in the textnode will be discarded
   wrapping.setAttributeNS(null, 'x', x_pos + padding);
   wrapping.setAttributeNS(null, 'y', y_pos + padding);

// Make a copy of this node and hide it to progressively draw, measure and calculate line breaks.

   var testing = wrapping.cloneNode(false);
   testing.setAttributeNS(null, 'visibility', 'hidden');  // Comment this out to debug

   var testingTSPAN = document.createElementNS(null, 'tspan');
   var testingTEXTNODE = document.createTextNode(textnode.textContent);
   testingTSPAN.appendChild(testingTEXTNODE);

   testing.appendChild(testingTSPAN);
   var tester = document.getElementsByTagName('svg')[0].appendChild(testing);

   var words = textnode.textContent.split(" ");
   var line = line2 = "";
   var linecounter = 0;
   var testwidth;

   for (var n = 0; n < words.length; n++) {

      line2 = line + words[n] + " ";
      testing.textContent = line2;
      testwidth = testing.getBBox().width;

      if ((testwidth + 2*padding) > boxwidth) {

        testingTSPAN = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');
        testingTSPAN.setAttributeNS(null, 'x', x_pos + padding);
        testingTSPAN.setAttributeNS(null, 'dy', line_height);

        testingTEXTNODE = document.createTextNode(line);
        testingTSPAN.appendChild(testingTEXTNODE);
        wrapping.appendChild(testingTSPAN);

        line = words[n] + " ";
        linecounter++;
      }
      else {
        line = line2;
      }
    }

    var testingTSPAN = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');
    testingTSPAN.setAttributeNS(null, 'x', x_pos + padding);
    testingTSPAN.setAttributeNS(null, 'dy', line_height);

    var testingTEXTNODE = document.createTextNode(line);
    testingTSPAN.appendChild(testingTEXTNODE);

    wrapping.appendChild(testingTSPAN);

    testing.parentNode.removeChild(testing);
    textnode.parentNode.replaceChild(wrapping,textnode);

    return linecounter;
}

document.getElementById('original').onmouseover = function () {

    var container = document.getElementById('destination');
    var numberoflines = wraptorect(this,container,20,1);
    console.log(numberoflines);  // In case you need it

};
Run Code Online (Sandbox Code Playgroud)


jbe*_*rd4 8

也可以使用JavaScript添加此功能.Carto.net有一个例子:

http://old.carto.net/papers/svg/textFlow/

还有一些其他可能有用的是你是可编辑的文本区域:

http://old.carto.net/papers/svg/gui/textbox/


zen*_*0lf 6

如果您使用d3.js,这可能会有所帮助:https://bl.ocks.org/mbostock/7555321


Pet*_*ter 5

以下代码运行正常。运行代码片段的功能。

也许可以将其清除或使其自动与SVG中的所有文本标签一起使用。

function svg_textMultiline() {

  var x = 0;
  var y = 20;
  var width = 360;
  var lineHeight = 10;
  
  

  /* get the text */
  var element = document.getElementById('test');
  var text = element.innerHTML;

  /* split the words into array */
  var words = text.split(' ');
  var line = '';

  /* Make a tspan for testing */
  element.innerHTML = '<tspan id="PROCESSING">busy</tspan >';

  for (var n = 0; n < words.length; n++) {
    var testLine = line + words[n] + ' ';
    var testElem = document.getElementById('PROCESSING');
    /*  Add line in testElement */
    testElem.innerHTML = testLine;
    /* Messure textElement */
    var metrics = testElem.getBoundingClientRect();
    testWidth = metrics.width;

    if (testWidth > width && n > 0) {
      element.innerHTML += '<tspan x="0" dy="' + y + '">' + line + '</tspan>';
      line = words[n] + ' ';
    } else {
      line = testLine;
    }
  }
  
  element.innerHTML += '<tspan x="0" dy="' + y + '">' + line + '</tspan>';
  document.getElementById("PROCESSING").remove();
  
}


svg_textMultiline();
Run Code Online (Sandbox Code Playgroud)
body {
  font-family: arial;
  font-size: 20px;
}
svg {
  background: #dfdfdf;
  border:1px solid #aaa;
}
svg text {
  fill: blue;
  stroke: red;
  stroke-width: 0.3;
  stroke-linejoin: round;
  stroke-linecap: round;
}
Run Code Online (Sandbox Code Playgroud)
<svg height="300" width="500" xmlns="http://www.w3.org/2000/svg" version="1.1">

  <text id="test" y="0">GIETEN - Het college van Aa en Hunze is in de fout gegaan met het weigeren van een zorgproject in het failliete hotel Braams in Gieten. Dat stelt de PvdA-fractie in een brief aan het college. De partij wil opheldering over de kwestie en heeft schriftelijke
    vragen ingediend. Verkeerde route De PvdA vindt dat de gemeenteraad eerst gepolst had moeten worden, voordat het college het plan afwees. "Volgens ons is de verkeerde route gekozen", zegt PvdA-raadslid Henk Santes.</text>

</svg>
Run Code Online (Sandbox Code Playgroud)

  • SVG 文本中的自动换行:) 当文本太长时,我的 javascript 代码会创建换行。如果我能处理 SVG 中的所有文本标签,那就太好了。自动,无需更改 javascript 中的 id=""。不幸的是,SVG 本身没有多行。 (2认同)