Programing

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

lottogame 2020. 8. 23. 09:40
반응형

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


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

<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를 어디서든 사용할 수 없습니다.


이것은 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에 삽입해야합니다.


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

 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 줄이 있습니다.


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

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

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

It splits the text on \\\n and for each puts each fragment in a tspan. Then it calculates the size of the box required based on the longest length of text and the number of lines. You will also need to change the tooltip text element to contain three tspans:

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

This assumes that you never have more than three lines. If you want more than three lines you can add more tspans and increase the length of the for loop.


I have adapted a bit the solution by @steco, switching the dependency from d3 to jquery and adding the height of the text element as parameter

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

참고URL : https://stackoverflow.com/questions/16701522/how-to-linebreak-an-svg-text-within-javascript

반응형