Respuestas:
El ajuste de texto no es parte de SVG1.1, la especificación actualmente implementada. Preferiría usar HTML a través del <foreignObject/>
elemento.
<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>
Aquí tienes una alternativa:
<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>
Teniendo en cuenta que, aunque se puede informar que ForeignObject es compatible con esa cadena de características, no hay garantía de que se pueda mostrar HTML porque no es requerido por la especificación SVG 1.1. Por el momento, no hay una cadena de características para el soporte de objetos html-in-foreigno. Sin embargo, todavía es compatible con muchos navegadores, por lo que es probable que sea necesario en el futuro, quizás con una cadena de características correspondiente.
Tenga en cuenta que el elemento 'textArea' en SVG Tiny 1.2 admite todas las características estándar de svg, por ejemplo, relleno avanzado, etc., y que puede especificar el ancho o el alto como automático, lo que significa que el texto puede fluir libremente en esa dirección. ForeignObject actúa como ventana gráfica de recorte.
Nota: si bien el ejemplo anterior es contenido SVG 1.1 válido, en SVG 2 se ha eliminado el atributo 'requiredFeatures', lo que significa que el elemento 'switch' intentará representar el primer elemento 'g' independientemente de que sea compatible con SVG 1.2 'textArea 'elementos. Consulte las especificaciones del elemento conmutador SVG2 .
xhtml:div
lugar de div
, pero eso podría deberse a d3.js. No pude encontrar ninguna referencia útil sobre TextFlow, ¿existe (todavía) o solo estaba en algún borrador?
TextPath puede ser bueno para algunos casos.
<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>
Basándome en el código de @Mike Gledhill, he dado un paso más y he añadido más parámetros. Si tiene un SVG RECT y desea que el texto se ajuste dentro de él, esto puede ser útil:
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
};
boxwidth = parseInt(boxObject.getAttribute('width'))
solo aceptaría ancho en píxeles, mientras queboxwidth = parseInt(boxObject.getBBox().width)
, aceptaría cualquier tipo de unidad de medida
Esta funcionalidad también se puede agregar usando JavaScript. Carto.net tiene un ejemplo:
http://old.carto.net/papers/svg/textFlow/
Otra cosa que también puede ser útil son las áreas de texto editables:
El siguiente código está funcionando bien. Ejecute el fragmento de código que hace.
Tal vez se pueda limpiar o hacer que funcione automáticamente con todas las etiquetas de texto en 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>
He publicado el siguiente tutorial para agregar algunos ajustes de palabras falsos a un elemento de "texto" SVG aquí:
Envoltorio de palabras SVG - ¿Mostrar tapón?
Solo necesita agregar una función JavaScript simple, que divide su cadena en elementos "tspan" más cortos. A continuación, se muestra un ejemplo de cómo se ve:
Espero que esto ayude !