자바 스크립트 내에서 svg 텍스트를 줄 바꿈하는 방법은 무엇입니까?


107

그래서 내가 가진 것은 다음과 같습니다.

<path class="..." onmousemove="show_tooltip(event,'very long text 
    \\\n I would like to linebreak')" onmouseout="hide_tooltip()" d="..."/>

<rect class="tooltip_bg" id="tooltip_bg" ... />
<text class="tooltip" id="tooltip" ...>Tooltip</text>

<script>
<![CDATA[
function show_tooltip(e,text) {
    var tt = document.getElementById('tooltip');
    var bg = document.getElementById('tooltip_bg');

    // set position ...

    tt.textContent=text;

    bg.setAttribute('width',tt.getBBox().width+10);
    bg.setAttribute('height',tt.getBBox().height+6);

    // set visibility ...
}
...

이제 내 매우 긴 도구 설명 텍스트에는 alert ()를 사용하더라도 줄 바꿈이 없습니다. 텍스트에 실제로 두 줄이 있음을 보여줍니다. ( "\"가 포함되어 있습니다. 그런데 어떻게 제거합니까?)
CDATA를 어디서든 사용할 수 없습니다.


2
svgjs.com/textflow 가 툴팁에 도움 이 될 수 있습니까?
앨빈 K.

@AlvinK. 링크가 끊어졌습니다. 새 위치를 찾으려고했지만 실패했습니다.
guettli

답변:


150

이것은 SVG 1.1이 지원하는 것이 아닙니다. SVG 1.2에는 textArea자동 줄 바꿈 기능 이있는 요소가 있지만 모든 브라우저에서 구현되지는 않습니다. SVG 2는 실시 계획하지 않습니다textArea ,하지만이 있나요 자동 포장 텍스트를 .

그러나 이미 바꿈이 발생하는 위치를 알고 주어진 여러에 텍스트를 깰 수 <tspan>와의 각각 x="0"dy="1.4em"텍스트의 실제 라인을 시뮬레이션 할 수 있습니다. 예를 들면 :

<g transform="translate(123 456)"><!-- replace with your target upper left corner coordinates -->
  <text x="0" y="0">
    <tspan x="0" dy="1.2em">very long text</tspan>
    <tspan x="0" dy="1.2em">I would like to linebreak</tspan>
  </text>
</g>

물론 자바 스크립트에서 그렇게하고 싶기 때문에 각 요소를 수동으로 생성하고 DOM에 삽입해야합니다.


2
그리고 어디에 넣을지 어떻게 알 수 <tspan>s있습니까? 바꾸다? 스플릿?
sollniss

2
시도해 var tspan = document.createElement('tspan') tspan.setAttribute('x','0'); tspan.setAttribute('dy','1.2em'); tspan.textContent = text; tt.appendChild(tspan); 도 텍스트가 전혀 표시되지 않습니다.
sollniss

2
x = '0'dy = '1.2em' 이 필요한 이유에 대해 자세히 설명 하시겠습니까 ? 당신이 말한 것처럼 실제로 작동합니다. 그러나 이러한 속성 없이도 작동 할 것으로 예상했습니다. 대신 아무것도 표시되지 않습니다 ... 또한 줄 바꿈 이 발생 하는 이유 가 전혀 명확하지 않습니다 . 컨테이너의 너비를 고정하여 줄 바꿈을 적용 할 수 있도록 설정 한 것과는 다릅니다.
Konrad Viltersten 2016 년

4
x=0절대 좌표 : 텍스트 조각을 현재 좌표계 의 원점으로 이동합니다 . 요소 의 transform속성 g은 새 현재 좌표계를 정의하고 텍스트가 왼쪽 정렬되어 있다고 가정하면 tspan이 왼쪽으로 이동합니다. 이것은 캐리지 리턴 명령처럼 작동합니다. dy=1.2emA는 상대가 현재 텍스트 조각의 상대 크기에 의해 텍스트 단편 이동 : 좌표. 이것은 줄 바꿈 명령처럼 작동합니다. 결합하면 CR / LF를 얻습니다.
Sergiu Dumitriu

아직 시도하지 않음 : 그룹 없이도 할 수 있습니까? <text x = "100"y = "100"> <tspan x = "100"y = "100"> 매우 긴 텍스트 </ tspan> <tspan x = "100"y = "115"> 줄 바꿈 </ tspan> </ text> ??
Richard

25

나는 당신이 이미 그것을 해결할 수 있다고 확신하지만 누군가가 비슷한 해결책을 찾고 있다면 이것은 나를 위해 일했습니다.

 g.append('svg:text')
  .attr('x', 0)
  .attr('y', 30)
  .attr('class', 'id')
  .append('svg:tspan')
  .attr('x', 0)
  .attr('dy', 5)
  .text(function(d) { return d.name; })
  .append('svg:tspan')
  .attr('x', 0)
  .attr('dy', 20)
  .text(function(d) { return d.sname; })
  .append('svg:tspan')
  .attr('x', 0)
  .attr('dy', 20)
  .text(function(d) { return d.idcode; })

줄 바꿈으로 구분 된 3 줄이 있습니다.


21
FWIW : OP가 순수 JavaScript를 사용하는 것 같습니다. 이 답변은 D3를 활용하는 것으로 보입니다 .
Ben Mosher

나는 D3를 사용하고 있으며 귀하의 접근 방식이 저에게 효과적이었습니다. 게시 해 주셔서 감사합니다. 다음과 같이 새 tspan을 추가하기 전에 먼저 이전 tspan을 삭제해야한다는 것을 알았습니다. focus.selectAll ( "tspan"). remove ();
Darren Parker

1
.append ()를 연결하므로 <tspan> 태그가 중첩된다는 점에주의하십시오. 이로 인해 수행하려는 작업에 따라 CSS에 약간의 두통이 발생할 수 있습니다.
seneyr

@seneyr
bszom

16

tspan 솔루션을 사용하여 줄 바꿈을 어디에 둘지 미리 알지 못한다고 가정 해 봅시다.이 멋진 기능을 사용할 수 있습니다. 여기에서 찾은 것입니다. http://bl.ocks.org/mbostock/7555321

그러면 주어진 너비의 픽셀에 대해 긴 텍스트 svg의 줄 바꿈이 자동으로 수행됩니다.

function wrap(text, width) {
  text.each(function() {
    var text = d3.select(this),
        words = text.text().split(/\s+/).reverse(),
        word,
        line = [],
        lineNumber = 0,
        lineHeight = 1.1, // ems
        y = text.attr("y"),
        dy = parseFloat(text.attr("dy")),
        tspan = text.text(null).append("tspan").attr("x", 0).attr("y", y).attr("dy", dy + "em");
    while (word = words.pop()) {
      line.push(word);
      tspan.text(line.join(" "));
      if (tspan.node().getComputedTextLength() > width) {
        line.pop();
        tspan.text(line.join(" "));
        line = [word];
        tspan = text.append("tspan").attr("x", 0).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word);
      }
    }
  });
}

9

나는 이것이 당신이 원하는 것을한다고 생각합니다.

function ShowTooltip(evt, mouseovertext){
    // Make tooltip text        
    var tooltip_text = tt.childNodes.item(1);
    var words = mouseovertext.split("\\\n");
    var max_length = 0;

    for (var i=0; i<3; i++){
        tooltip_text.childNodes.item(i).firstChild.data = i<words.length ?  words[i] : " ";
        length = tooltip_text.childNodes.item(i).getComputedTextLength();
        if (length > max_length) {max_length = length;}
    }

    var x = evt.clientX + 14 + max_length/2;
    var y = evt.clientY + 29;
    tt.setAttributeNS(null,"transform", "translate(" + x + " " + y + ")")

    // Make tooltip background
    bg.setAttributeNS(null,"width", max_length+15);
    bg.setAttributeNS(null,"height", words.length*15+6);
    bg.setAttributeNS(null,"x",evt.clientX+8);
    bg.setAttributeNS(null,"y",evt.clientY+14);

    // Show everything
    tt.setAttributeNS(null,"visibility","visible");
    bg.setAttributeNS(null,"visibility","visible");
}

텍스트를 분할하고 \\\n각 조각을 tspan에 넣습니다. 그런 다음 가장 긴 텍스트 길이와 줄 수를 기반으로 필요한 상자의 크기를 계산합니다. 또한 세 개의 tspan을 포함하도록 도구 설명 텍스트 요소를 변경해야합니다.

<g id="tooltip" visibility="hidden">
    <text><tspan>x</tspan><tspan x="0" dy="15">x</tspan><tspan x="0" dy="15">x</tspan></text>
</g>

이것은 당신이 세 줄을 넘지 않는다고 가정합니다. 3 줄 이상을 원하면 tspan을 더 추가하고 for 루프의 길이를 늘릴 수 있습니다.


"\\\n"보다는 "\n"?
ralien

2

I은 종속성을 스위칭 비트를 @steco하여 용액을 적응 d3jquery상기 추가 height파라미터로서 텍스트 요소를

function wrap(text, width, height) {
  text.each(function(idx,elem) {
    var text = $(elem);
    text.attr("dy",height);
        var words = text.text().split(/\s+/).reverse(),
        word,
        line = [],
        lineNumber = 0,
        lineHeight = 1.1, // ems
        y = text.attr("y"),
        dy = parseFloat( text.attr("dy") ),
        tspan = text.text(null).append("tspan").attr("x", 0).attr("y", y).attr("dy", dy + "em");
    while (word = words.pop()) {
      line.push(word);
      tspan.text(line.join(" "));
      if (elem.getComputedTextLength() > width) {
        line.pop();
        tspan.text(line.join(" "));
        line = [word];
        tspan = text.append("tspan").attr("x", 0).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word);
      }
    }
  });
}

2

자바 스크립트 대신 HTML 사용

<html>
  <head><style> * { margin: 0; padding: 0; } </style></head>
  <body>
    <h1>svg foreignObject to embed html</h1>

    <svg
      xmlns="http://www.w3.org/2000/svg"
      viewBox="0 0 300 300"
      x="0" y="0" height="300" width="300"
    >

      <circle
        r="142" cx="150" cy="150"
        fill="none" stroke="#000000" stroke-width="2"
      />

      <foreignObject
        x="50" y="50" width="200" height="200"
      >
        <div
          xmlns="http://www.w3.org/1999/xhtml"
          style="
            width: 196px; height: 196px;
            border: solid 2px #000000;
            font-size: 32px;
            overflow: auto; /* scroll */
          "
        >
          <p>this is html in svg 1</p>
          <p>this is html in svg 2</p>
          <p>this is html in svg 3</p>
          <p>this is html in svg 4</p>
        </div>
      </foreignObject>

    </svg>

</body></html>


난 당신이 "대신 자바 스크립트의 사용 SVG"을 의미 생각
발레 Bozz

저에게 가장 적합한 솔루션 인 "HTML in SVG"입니다!
Kévin Berthommier
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.