Interactuando con SVG
Estos días de atrás comencé a dar unas clases
extracurriculares1 sobre robótica en un colegio de Zaragoza.
Es un colegio concertado laico que da buen servicio a una población
con un amplio asentamiento de población migrante y de otros colectivos
en peligro de exclusión. El proyecto me pareció interesante y, aparte
del dinero que pagan ─que es poco, porque son dos horas a la semana─,
me atrajo en cuanto me lo propusieron. Todo lo que hago me lo suelo
tomar en serio y estas clases no son una excepción. Preparándolas me
he llegado a liar con presentaciones e interacciones con elementos
educativos que hasta ahora no había tocado. Por ejemplo, me hice una
imagen svg
de la tarjeta micro2 que utilizaremos en el
aula. Sin embargo, quería que esa imagen fuera interactiva y en este
artículo os cuento un poco de mis investigaciones sobre añadir
interacción a los gráficos vectoriales desde javascript
. Como veis,
otra vez hago de psicólogo metido a programador.
El formato SVG
No creo descubrir a nadie cómo es el formato SVG
, si digo que dicho
formato es, básicamente, una clase de XML
concebida para guardar
objetos gráficos en su estructura. Hay mucha información sobre él a
través de Internet. Podemos escribir el código XML
directamente en
un buffer de Emacs o editarlo como un gráfico vectorial con
Inkscape. Por ejemplo, podemos escribir el siguiente código:
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg viewbox="0 0 250 100" width="250" height="100"> <!-- Creo un círculo --> <circle cx="50" cy="50" r="40" stroke="#006600" stroke-width="4" fill="#00cc00"/> </svg>
El resultado se puede visualizar directamente en Emacs, como he dicho, pero lo podemos abrir también en Inkscape para una edición gráfica más cómoda:
Si lo abrimos en Emacs podemos alternar entre el gráfico
y el código que lo genera, sólo pulsando C-c C-c
.
¿Cuándo elegir un modo u otro de edición? Pues depende fundamentalmente del usuario. Para mi gusto, cuando los gráficos son sencillos, como el anterior, hacerlo con el texto de forma directa tampoco es muy complicado. Sin embargo, cuando se avanza en complejidad el manejo del gráfico en un buffer de texto y poder imaginarse el resultado que acarreará el texto que estamos escribiendo, se puede complicar mucho y para ello es recomendable utilizar un editor como Inkscape.
Sin embargo, si vamos a incluir javascript
en el archivo, al final
lo tendremos que editar en modo texto, pues Inkscape no permite, por
lo menos todavía, añadir código de forma directa.
Incluir gráficos vectoriales en html
Dentro de una etiqueta img
La principal ventaja de incluir gráficos vectoriales en nuestra
página, es que se puede escalar sin problemas de pixelado. Además,
el formato .svg
es un estándar soportado por la mayoría de los
navegadores. Quizá haya problemas con los más antiguos, pero incluso
Internet Explorer comenzó a soportarlo desde su versión 9.
El caso es que hay varias formas de incrustar contenido svg
en un
fichero html
. De primeras pensé que daría igual cualquiera de las
maneras que hay. Puesto que la forma más simple de editar un gráfico
vectorial es con alguna aplicación que facilite la tarea como Inkscape,
lo utilicé para dibujar la tarjeta por sus dos lados:
También tengo imágenes separadas para ilustrar los eventos que se producen. Lo que quería conseguir eran algunos efectos simples, como que se iluminaran los leds cuando pasara el ratón por encima o que al «pulsar uno de los botones» se iluminaran todos.
El gráfico así generado es de buena calidad y se visualiza
correctamente independientemente del tamaño de la imagen generada. El
problema es que cuando se importa como se haría con cualquier fichero
gráfico, no se puede acceder a los objetos internos. Probé a meterle
el javascript
dentro de la imagen. El problema es que algunos
eventos los realizaba correctamente y otros no. Por ejemplo, no me
captura bien el onclick
.
Necesitaba probar otros métodos para hacerlo interactivo, pero dada la
complejidad del svg
que necesitaba, no me atreví a hacerlo mediante
código y preferí mantener los gráficos dibujados con Inkscape aunque
lo que hice fue copiar directamente luego el contenido del fichero
gráfico en una página html
dentro de una etiqueta svg
. Esta
etiqueta dentro de un fichero html5
se comporta como cualquier otra
etiqueta y puede contener etiquetas tanto svg
como html
. En el
ejemplo de más adelante lo veremos mejor ilustrado.
La etiqueta svg
a pelo
Esta opción es la más funcional para lo que quiero hacer. ¿Qué ventajas tiene?
- Se carga rápidamente porque el código está en el interior del mismo
html
. - Se puede dar formato a los objetos desde la hoja de estilos
css
. - Los objetos internos del
svg
son accesibles desdeDOM
.
Por contra, no es tan impermeable como cargar un fichero de gráficos
externos: hay que tener cuidado con que no nos cambie los tipos de
letra u otras opciones. Si el fichero gráfico es muy complejo y optas
por copiar el código XML
interno, después de haberlo hecho o
modificado con Inkscape, tienes que quitar algunas etiquetas
exclusivas del editor, no aportan nada, el navegador las ignorará,
pero no dejan de ser peso muerto en el mismo gráfico.
Interacción
Para ilustrar el artículo, he hecho un pequeño documento html
para
interactuar con objetos svg
desde el contenido del documento. No he
querido complicarlo demasiado. Apenas son dos objetos rectangulares y
un objeto input
que sirve para establecer el redondeo de las
esquinas de dichos rectángulos. Cuando dicho redondeo de esquinas es
igual al ancho del objeto, parece un círculo, mientras que cuando el
valor de redondeo es 0 la figura es un perfecto cuadrado. Además en
uno de ellos se invierten los valores, de modo que mientras uno es
redondo el otro es cuadrado. Cuando el valor del input
sea 20 (el
valor medio) ambos cuadrados serán idénticos.
<!DOCTYPE html> <html> <head> <title>SVG la cuadratura del círculo</title> <meta charset="UTF-8"> </head> <body> <h1 align="center">La cuadratura del círculo</h1> <!-- Se pueden utilizar estilos para el objeto SVG --> <style> .verde { stroke: #006600; fill : #00cc00; } .rojo { stroke: #660000; fill : #cc0000; } </style> <!-- Se pueden agrupar elementos SVG en otros objetos HTML --> <p align="center"> <svg viewBox="0 0 250 100" width="250" height="100"> <a target="_blank" xlink:href="https://www.w3.org/Graphics/SVG/"> <rect id="circulo" x="50" y="10" rx="40" ry="40" height="80" width="80" stroke-width="4" class="verde"/> </a> <rect id="cuadrado" x="150" y="10" rx="0" ry="0" height="80" width="80" stroke-width="4" class="rojo"/> </svg> </p> <div align="center"> <!-- Las interacciones pueden realizarse a través de formularios --> <input type="range" id="rango" min="0" max="40" value="40" oninput="cuadratura(this.value)" width="250"> <p id="etiqueta">40</p> </div> <script> function cuadratura(value) { // Establece el valor de redondeo de las esquinas de los dos // objetos del SVG. Obsérvese que se obtienen mediante `Id` var circulo = document.getElementById("circulo"); var cuadrado = document.getElementById("cuadrado"); var etiqueta = document.getElementById("etiqueta"); circulo.setAttribute("rx", value); circulo.setAttribute("ry", value); cuadrado.setAttribute("rx", 40 - value); cuadrado.setAttribute("ry", 40 - value); etiqueta.innerHTML = value; } </script> </body> </html>
Dicho código genera la siguiente página:
Se pueden apreciar tres partes fundamentales en el código:
- Una parte de estilos (sólo para mostrar que, efectivamente, se
pueden afectar los estilos del
svg
desde los estilos de la página). - Una parte
svg
donde se define elviewbox
y un par de formas, que serán las que cambien con los valores del formulario que hay justo a continuación. - Un
script
que modifica los distintos objetos de la página: los dos internos alsvg
y la etiquetahtml
que muestra el valor.
No he querido hacer un formulario completo para esto, sólo he puesto
un objeto input
de tipo range
para hacer las modificaciones.
Además en ese mismo elemento se llama al javascript
, concretamente a
la función cuadratura()
con el propio value
del input
como
parámetro. También se puede observar que en el código svg
se pueden
añadir etiquetas html
, como por ejemplo, la etiqueta <a>
para
enlazar a otras direcciones web. Si pinchas en el objeto verde te
abrirá la página oficial de la organización w3 sobre los gráficos
svg
. Es sencillo, por tanto poder hacer cualquier gráfico
interactivo, aunque sea sólo a base de poner enlaces a otras páginas
dentro del contenido svg
.
Si no quieres copiar el código anterior en un fichero html
y
trastearlo, puedes interactuar con este código embebido en el mismo
artículo.
40
Conclusiones
Estos días he aprendido mucho de las estructuras internas que se
manejan en un svg
. Mucho del código que he trasteado lo he hecho con
Emacs viendo cómo los cambios en el texto se convertían en cambios
gráficos.
Nunca me había puesto a meterle código a un gráfico vectorial, pero no es nada complicado hacerlo.
Footnotes:
Las extraescolares de toda la vida, pero que las cambian el nombre por aquello de que parezcan más modernas.
Comentarios