Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/svg/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在javascript中换行svg文本?_Javascript_Svg_Newline_Line Breaks - Fatal编程技术网

如何在javascript中换行svg文本?

如何在javascript中换行svg文本?,javascript,svg,newline,line-breaks,Javascript,Svg,Newline,Line Breaks,这就是我所拥有的: <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

这就是我所拥有的:

<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支持的功能。SVG1.2确实有
textArea
元素,具有自动换行功能,但并不是在所有浏览器中都实现。SVG2,但它确实有

但是,如果您已经知道换行符应该出现在何处,则可以将文本拆分为多个
s,每个
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>

很长的文本
我想换行

当然,由于您希望从JavaScript执行此操作,因此必须手动创建每个元素并将其插入DOM。

我认为这符合您的要求:

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

这假设您的行数不会超过三行。如果您需要三行以上的行,您可以添加更多的TSPAN并增加for循环的长度。

我支持您已经设法解决了这个问题,但是如果有人正在寻找类似的解决方案,那么这对我很有效:

 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解决方案,假设您事先不知道换行符放在哪里:您可以使用我在这里找到的这个很好的函数:

它会自动为给定宽度(以像素为单位)的长文本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);
      }
    }
  });
}

我对@steco的解决方案做了一些修改,将依赖关系从
d3
切换到
jquery
,并添加文本元素的
高度作为参数

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

使用HTML而不是javascript


*{边距:0;填充:0;}
svg foreignObject以嵌入html
这是SVG1中的html

这是SVG2中的html

这是SVG3中的html

这是SVG4中的html


以及如何识别将
s
放在何处?代替Split?试用了
var tspan=document.createElement('tspan')tspan.setAttribute('x','0');tspan.setAttribute('dy','1.2em');tspan.textContent=文本;tt.appendChild(tspan)
根本不显示任何文本。您是否愿意详细说明为什么需要x='0'dy='1.2em'?正如你所说的,它确实有效。然而,我期望它即使没有这些属性也能工作。相反,没有显示任何内容。。。另外,我也不完全清楚为什么会发生换行。这不像是我们将容器的宽度设置为某个固定值,以便它可以强制换行,是吗?
x=0
是一个绝对坐标:将文本片段移动到文本的原点。
g
元素上的
transform
属性定义了一个新的当前坐标系,并假设文本左对齐,则tspan将向左移动。这类似于回车指令
dy=1.2em
是一个相对坐标:相对于当前文本片段移动文本片段此数量。这类似于换行指令。结合起来,你会得到一个CR/LF。还没有尝试过这个:你能在没有团队的情况下也这样做吗?很长的文本我想换行??FWIW:看起来OP使用的是纯JavaScript;这个答案似乎是杠杆作用。我使用的是D3,你的方法对我很有效。谢谢你发帖。我发现我需要先删除旧的tspan,然后再添加新的tspan,如下所示:focus.selectAll(“tspan”).remove();使用这种方法时要注意,它嵌套了标记,因为它链接了.append()。这可能会导致CSS的一些小问题,具体取决于您想做什么。请参阅以获取避免@seneyrw所述嵌套的方法。为什么是
“\\\n”
而不是
“\n”
?我想您的意思是“使用SVG而不是JavaScript”?这是“SVG中的HTML”,对我来说是最好的解决方案!
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);
      }
    }
  });
}