Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

387
Vistas
Manera correcta de cambiar un SVG <text> sin cambiar sus hijos <tspan>

Considere este SVG simple con un elemento <text> que contiene algunos <tspan> s:

 <svg> <text x="10" y="30"> Foo Bar Baz <tspan x="30" dy="30">FooBar</tspan> <tspan x="30" dy="30">FooBaz</tspan> </text> </svg>

Ahora supongamos que queremos cambiar el valor del texto en sí (en este caso, "Foo Bar Baz" ) manteniendo sus descendientes <tspan> . Si usamos textContent , innerHTML (los navegadores modernos son compatibles con innerHTML para SVG), etc., eso reemplazará todo, incluidos los niños:

 document.querySelector("text").textContent = "New Foo";
 <svg> <text x="10" y="30"> Foo Bar Baz <tspan x="30" dy="30">FooBar</tspan> <tspan x="30" dy="30">FooBaz</tspan> </text> </svg>

Una solución es obtener el primer elemento NodeList de los nodos secundarios, que normalmente es el texto mismo:

 document.querySelector("text").childNodes[0].textContent = "New Foo";
 <svg> <text x="10" y="30"> Foo Bar Baz <tspan x="30" dy="30">FooBar</tspan> <tspan x="30" dy="30">FooBaz</tspan> </text> </svg>

Sin embargo, esta solución es bastante complicada. "¿Por qué?" , podría preguntar... bueno, usar un índice codificado en una colección es lo suficientemente complicado para mí. Además, como escribí anteriormente, el primer elemento de la colección normalmente es el texto mismo, pero no tengo idea si esto depende de la implementación y, por lo tanto, un nuevo navegador puede simplemente cambiar ese orden en la colección, implementando una secuencia diferente. .

De ahí la forma correcta en el título de mi pregunta: ¿hay una propiedad o algún otro método para cambiar específicamente el contenido del texto solo en un elemento SVG <text> ?

over 4 years ago · Santiago Trujillo
5 Respuestas
Responde la pregunta

0

Como yo lo veo tienes dos opciones. 1) Sobre la base de su último ejemplo donde busca el nodo de texto. Sabes que hay un nodo de texto con contenido. Puede probar todos los childNodes de <text> para ver si es un nodo de texto y luego reemplazar ese nodo. 2) Convierte el nodo de texto en un elemento <tspan> al igual que los otros elementos secundarios. Esto no hará ninguna diferencia visualmente y, al mismo tiempo, es más fácil referirse al elemento y diseñarlo si es necesario. El "costo" por agregar este elemento es mínimo.

 document.querySelector("text > .first").textContent = "New Foo";
 <svg> <text x="10" y="30"> <tspan class="first">Foo Bar Baz</tspan> <tspan x="30" dy="30">FooBar</tspan> <tspan x="30" dy="30">FooBaz</tspan> </text> </svg>

over 4 years ago · Santiago Trujillo Denunciar

0

Puede usar la propiedad nodeType en un bucle. Es importante tener en cuenta que el analizador puede agregar otros nodos de texto, por lo que también debe elegir cuál necesita. Una implementación simple sustituye el primer nodo con nodeType===3 . Son posibles otras implementaciones, teniendo en cuenta que otros nodos de tipo 3 tendrán textos simples como \n . Esto sustituirá el primer nodo de texto (no tspan ) que tiene alguna letra:

 const r = document.querySelector("text"); let hasText = /\w/; for (x = 0; x < r.childNodes.length; x++){ if (r.childNodes[x].nodeType === 3 && hasText.test(r.childNodes[x].textContent)){ r.childNodes[x].textContent = "New Foo"; break; } }
 <svg> <text x="10" y="30"> <tspan x="30" dy="30">FooBar</tspan> <tspan x="30" dy="30">FooBaz</tspan> Foo Bar Baz </text> </svg>

over 4 years ago · Santiago Trujillo Denunciar

0

Este mismo enfoque que hizo vqf con algunos hizo mejoras.

 const element = document.querySelector('text'); function changeText(text, node) { for (const n of node.childNodes) { let string = n.textContent.trim(); if (!n.hasChildNodes() && string !== '') { n.textContent = text; } } } changeText('New Foo Baz', element);
 <svg> <text x="10" y="30"> Foo Bar Baz <tspan x="30" dy="30">FooBar</tspan> <tspan x="30" dy="30">FooBaz</tspan> </text> </svg>

La segunda forma simplemente limpia la primera línea y agrega texto nuevo usando insertAdjacentText que brinda un enfoque más flexible.

 const element = document.querySelector('text'); function changeText(text, node) { for (const n of node.childNodes) { let string = n.textContent.trim(); if (!n.hasChildNodes() && string !== '') { n.textContent = ''; } } node.insertAdjacentText('afterbegin', text); node.insertAdjacentText('beforeend', text); } changeText('New Foo Baz', element);
 <svg> <text x="10" y="30"> Foo Bar Baz <tspan x="30" dy="30">FooBar</tspan> <tspan x="30" dy="30">FooBaz</tspan> </text> </svg>

over 4 years ago · Santiago Trujillo Denunciar

0

Un enfoque diferente a los demás. Reemplace los nodos Element.children directamente usando Element.replaceChildren() (No compatible con IE):

 const textNode = document.querySelector('text'); function updateTextContent(node, text) { node.replaceChildren(text, ...node.children); } updateTextContent(textNode, 'New Foo');
 <svg> <text x="10" y="30"> Foo Bar Baz <tspan x="30" dy="30">FooBar</tspan> <tspan x="30" dy="30">FooBaz</tspan> </text> </svg>

Si necesita soporte para IE, reemplace el valor de la propiedad textContent y luego useappend para agregar los nodos secundarios:

 function updateTextContent(node, text) { const children = [...node.children]; node.textContent = ""; node.append(text, ...children); }
over 4 years ago · Santiago Trujillo Denunciar

0

"¿Existe una propiedad o algún otro método para cambiar específicamente el contenido del texto solamente?"

No, probablemente no. De hecho, creo que podría ser mejor que tal método no exista. Digamos, por ejemplo, que su nodo <text> se veía así:

 <text> Foo <tspan>Bar</tspan> Baz </text>

Y ahora llamaríamos al método desconocido para cambiar el texto a Hello world . ¿Cuál sería el resultado deseado?

 <text> Hello world <tspan>Bar</tspan> </text>
 <text> <tspan>Bar</tspan> Hello world </text>

o incluso

 <text> Hello <tspan>Bar</tspan> world </text>

Mirándolo así, queda claro que el "contenido de texto" no puede verse como un caso especial que existe aparte del árbol de nodos: al igual que <tspan> en su ejemplo, puede haber múltiples nodos de texto en cualquier orden y cantidad. Por lo tanto, es difícil justificar un método especial que solo cambia los nodos de texto, sin introducir un método para cambiar solo todos los <tspan> , <div> , etc.

Soluciones

Si considera todos los nodos de texto como una especie de elementos sin tipo como este:

 <text> <text>Foo</text> <tspan>Bar</tspan> <text>Baz</text> </text>

hay pocas dudas sobre cómo abordaría la orientación y el cambio de su elemento deseado. Las opciones incluyen:

  • Agárralo por índice (como ya lo hiciste). A juzgar por el fragmento ficticio anterior, sería bastante seguro asumir que Foo siempre será el primer elemento. Pero al igual que con el :first selector en CSS, es posible que prefiera no depender tan rígidamente de una estructura específica.
  • Un atributo class="text" sería muy claro, pero luego necesitaría envolver su texto en un elemento real (que podría ser la mejor solución, pero estoy siguiendo sus especificaciones aquí).
  • Tome el primer elemento que sea del tipo correcto, tal como lo haría con cualquier otro elemento.

Por lo tanto, el fragmento a continuación sería una forma perfectamente válida de modificar el primer nodo de texto en una lista de elementos secundarios (escrito de manera funcional para que sea conciso).

 Array.from(document.querySelector("text").childNodes) .find(e => e.nodeType === Node.TEXT_NODE) .textContent = "New Foo";
 <svg> <text x="10" y="30"> Foo Bar Baz <tspan x="30" dy="30">FooBar</tspan> <tspan x="30" dy="30">FooBaz</tspan> </text> </svg>

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda