Texto creado dinamicamente

facebook-svg gplus-svg twitter-svg

En JavaScript, para crear un elemento <text> o cualquier otro elemento SVG necesitamos utilizar el método createElementNS

const SVG_NS = 'http://www.w3.org/2000/svg';// define el espacio de nombres
let text = document.createElementNS(SVG_NS, 'text');

Qué son los espacios de nombre en SVG

También necesitamos darle al <text> un textContent, ya que sin el textContent el elemento <text> es un elemento vacío.

text.textContent = 'el texto que tu quieras';

A continuación agregamos el elemento <text> al svg y lo hacemos utilizando el método appendChild.

elSvg.appendChild(text);

const SVG_NS = 'http://www.w3.org/2000/svg';
let text = document.createElementNS(SVG_NS, 'text');
text.textContent = 'el texto que tu quieras';	
elSvg.appendChild(text);

Y ya tenemos un elemento <text> aunque no es un elemento muy interesante.  Almeno que el viewBox empiece con valores negativos en y ( por ejemplo viewBox='0 -50 200 100' ), o que el svg tenga overflow:visible no podemos ver este texto.

Un elemento <text> sin argumentos toma los valores por defecto que sitúan el texto en el origen del lienzo svg (x='0' y ='0'). Además el valor por defecto de dominant-baseline es auto lo que en modo de escritura horizontal (como el español) equivale a dominant-baseline = 'alphabetic'. Esto quiere decir que lo único que podremos ver son las astas descendentes de algunas letras como p o g.

Cómo alinear texto en SVG

En el siguiente ejemplo voy a centrar el texto en el medio del lienzo svg, o sea alrededor del punto x='50' y='25'. Así que voy a necesitar algunos atributos más:

text.setAttributeNS(null,'x',50);
text.setAttributeNS(null,'y',25);
text.setAttributeNS(null, 'dominant-baseline','middle');
text.setAttributeNS(null, 'text-anchor','middle');

A diferencia de x e y podemos declarar los otros dos atributos, dominant-baseline y text-anchor en CSS, aunque no hay que olvidar que los atributos de presentación tienen una especificidad muy baja, justo por encima de los estilos por defecto, y pueden ser fácilmente sobreescritos con reglas CSS.

text{
  dominant-baseline : middle;
  text-anchor : middle;
}

Cuando tenemos tantos atributos por definir en JavaScript, lo podemos hacer de una manera más eficiente si los ponemos dentro de un objeto:


let o = {
    props: {
      x: 50,
      y: 25,
      'font-size':10,
      'dominant-baseline': 'middle',
      'text-anchor': 'middle'
    },
    txtConent: 'el texto que tu quieras'
  };

Por favor observe que las propiedades que llevan guión aparecen entre comillas.

A continuación podemos escribir una función para crear cualquier elemento de <text>. La función toma como argumentos el elemento padre (al cual agregamos el texto), y un objeto ( como el de arriba ) que contiene las propiedades y el texto para el nuevo elemento:


function dibujarTexto(o, parent) {
    // crea un nuevo elemento de texto
    let text = document.createElementNS(SVG_NS, 'text');
   //itera el objeto o.props
    for (let name in o.props) {
      if (o.props.hasOwnProperty(name)) {
       // establece el valor de un nuevo atributo del elemento text
        text.setAttributeNS(null, name, o.props[name]);
      }
    }
    // define el texto del nuevo elemento
    text.textContent = o.txtConent;
    // agrega el texto al elemento padre
    parent.appendChild(text);
    // devuelve el elemento creado para el caso en el cual necesitamos utilizarlo de  nuevo
    return text;
  }

Reutilizar el elemento de texto

En el siguiente ejemplo hay un <input type='text' donde podemos escribir el texto que queramos que aparezca en el SVG.


el nombre:

Necesitamos también una función que actualiza el texto:


function actualizarTexto(text,txtConent){
    text.textContent = txtConent;
}

El primer argumento de esta función es el elemento <text> que queremos actualizar. El segundo argumento es el contenido del texto.


let txt = dibujarTexto(o, elSvg);// crea y dibuja un nuevo elemento text
//utilizamos el método addEventListener para detectar el cambio de valor del input #elNombre y utilizar el nuevo valor como textContent
elNombre.addEventListener('input', ()=>{actualizarTexto(txt,elNombre.value)})

See the Pen Crear un elemento de texto en SVG by Gabi (@enxaneta) on CodePen.