Как разбить текст svg в javascript?
Итак, вот что я имею:
<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 работать где угодно.
Ответы
Ответ 1
Это не то, что поддерживает SVG 1.1. SVG 1.2 имеет элемент textArea
с автоматическим переносом слов, но он не реализован во всех браузерах. SVG 2 не планирует реализацию textArea
, но имеет текст с автозавершением.
Однако, учитывая, что вы уже знаете, где должны происходить ваши строки, вы можете разбить свой текст на несколько <tspan>
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.
Ответ 2
Я, супруг, вам удалось решить это, но если кто-то ищет подобное решение, это сработало для меня:
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 линии, разделенные на строку.
Ответ 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);
}
}
});
}
Ответ 4
Я думаю, что это делает то, что вы хотите:
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. Затем он вычисляет размер поля, необходимого на основе самой длинной длины текста и количества строк. Вам также потребуется изменить текстовый элемент tooltip, чтобы он содержал три 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>
Это предполагает, что у вас никогда не будет более трех строк. Если вы хотите более трех строк, вы можете добавить больше tspans и увеличить длину цикла for.
Ответ 5
Я немного адаптировал решение @steco, переключив зависимость от d3
на jquery
и добавив 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);
}
}
});
}
Ответ 6
use replace, он удалит строки, если вы спросите его:)
Это заменит один разрыв строки:
text.replace("\n","");
И это заменит несколько:
//This javascript code removes all 3 types of line breaks
text = text.replace(/(\r\n|\n|\r)/gm,"");
https://developer.mozilla.org/en/docs/JavaScript/Reference/Global_Objects/String/replace