[xml] SVG 텍스트의 자동 줄 바꿈

HTML 텍스트가 요소를 채우는 것과 같은 방식으로 <text>컨테이너에 자동 줄 바꿈되는 내용을 SVG 에 표시하고 싶습니다 . 그것을 할 방법이 있습니까? 나는 s 를 사용하여 선을 아껴두고 싶지 않습니다 .<rect><div><tspan>



답변

텍스트 래핑은 현재 구현 된 사양 인 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>


답변

다음은 대안입니다.

<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>

foreignObject가 해당 기능 문자열로 지원되는 것으로보고 될 수 있지만 HTML이 SVG 1.1 사양에서 필요하지 않기 때문에 표시 될 수 있다는 보장은 없습니다. 현재 html-in-foreignobject 지원을위한 기능 문자열이 없습니다. 그러나 많은 브라우저에서 여전히 지원되므로 향후 해당 기능 문자열과 함께 필요할 수 있습니다.

SVG Tiny 1.2 의 ‘textArea’요소 는 모든 표준 svg 기능 (예 : 고급 채우기 등)을 지원하며 너비 또는 높이를 자동으로 지정할 수 있습니다. 즉, 텍스트가 해당 방향으로 자유롭게 흐를 수 있음을 의미합니다. ForeignObject는 클리핑 뷰포트 역할을합니다.

참고 : 위의 예는 유효한 SVG 1.1 콘텐츠이지만 SVG 2에서는 ‘requiredFeatures’속성이 제거되었습니다. 즉, ‘switch’요소가 SVG 1.2 ‘textArea에 대한 지원 여부에 관계없이 첫 번째’g ‘요소를 렌더링하려고 시도합니다. ‘요소. SVG2 스위치 요소 사양을 참조하십시오 .


답변

어떤 경우에는 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>


답변

@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

};


답변

이 기능은 JavaScript를 사용하여 추가 할 수도 있습니다. Carto.net에는 다음과 같은 예가 있습니다.

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

또한 유용 할 수있는 다른 것은 편집 가능한 텍스트 영역입니다.

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


답변

다음 코드는 잘 작동합니다. 코드 조각을 실행합니다.

정리하거나 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();
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;
}
<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>


답변

여기에 SVG “텍스트”요소에 가짜 단어 줄 바꿈을 추가하기위한 다음 연습을 게시했습니다.

SVG Word Wrap-스토퍼 표시?

문자열을 더 짧은 “tspan”요소로 분할하는 간단한 JavaScript 함수를 추가하기 만하면됩니다. 다음은 그 모습의 예입니다.

SVG 예

도움이 되었기를 바랍니다 !