Primeros pasos con los SVG de HTML5: Agrupando elementos comunes
- Andrés Cruz
En la entrada anterior dimos los primeros pasos con los SVGs mediante la construcción de un semáforo, el cual consistía en un rectángulo con 3 círculos alineados en el eje vertical, vimos algunos de sus atributos para definir el tamaño de los círculos mediante el radio (atributo r
) y la posición de los mismos (mediante los atributos cx
y cy
) y el color de los mismos mediante el atributo fill
puedes consultar la entrada en el siguiente enlace:
Primeros pasos con los SVG de HTML5: Creando un sencillo semáforo
Ahora, en esta entrada vamos a organizar el código anterior para mejorar un poco su legibilidad y estructura en general; para ello lo primeros que vamos hacer es agrupar ciertos atributos comunes.
Agrupando elementos con atributos comunes con la etiqueta g
Vamos a emplear la etiqueta g
para agrupar los tres círculos que representan las luces del semáforo:
<svg width="200px" height="400px"> <rect x="0" y="0" width="150" height="350" fill="black" stroke="gray" stroke-width="2" /> <g stroke="black" stroke-width="2" stroke="gray"> <circle r="40" cx="75" cy="80" fill="red" /> <circle r="40" cx="75" cy="175" fill="yellow" /> <circle r="40" cx="75" cy="275" fill="green" /> </g> </svg>
g
podemos agrupar para evitar repetir algunos atributos en común y también nos ayuda en la organización de los mismos.
El porqué no están incluidos los atributos cx
, cy
y r
se debe a que estos atributos son específicos de los círculos, y la etiqueta g
permite definir solo atributos comunes y fundamentales de las figuras geométricas como las que están definidas en el ejemplo anterior.
Definiendo los estilos en una estructura aparte
Para mejorar la legibilidad aún más de nuestro ejemplo anterior, podemos definir el grosor del borde así como el color de los mismos desde CSS y así quitamos los atributos que realizaban esta tarea, más no podemos hacer lo mismo con el color de fondo.
Inclusive podemos definir un estilo en un elemento padre para que sea heredado por sus hijos, por ejemplo colocamos sobre el elemento g
un estilo style="fill:red"
que será tomado por sus hijos siempre y cuando estos no lo sobrescriban:
<svg width="200px" height="400px"> <style type="text/css"> rect, circle { stroke: #FFF; stroke-width: 3; } </style> <rect x="0" y="0" width="150" height="350" fill="black" stroke="gray" stroke-width="2" /> <g style="fill:red"> <circle r="40" cx="75" cy="80" /> <circle r="40" cx="75" cy="175" fill="yellow" /> <circle r="40" cx="75" cy="275" fill="green" /> </g> </svg>
En este ejemplo podemos ver cómo definimos un estilo común para las etiquetas rect
y circle
y luego se sobrescriben para todos los círculos a excepción del primero.
style
que tiene que estar embebido dentro del elemento que representa a la figura; por ejemplo style="fill:blue;"
tiene el mismo efecto que emplear fill="blue"
.Podemos agregar clases en nuestras figuras geométricas; por ejemplo, dejemos prendida una sola luz y cambiemos el grosor de la misma:
<svg width="200px" height="400px"> <style type="text/css"> rect { stroke: #FFF; stroke-width: 3; } .border { stroke: #FFF; stroke-width: 4; } </style> <rect x="0" y="0" width="150" height="350" fill="black" stroke="gray" stroke-width="2" /> <g> <circle r="40" cx="75" cy="80" class="border" style="fill:red"/> <circle r="40" cx="75" cy="175"/> <circle r="40" cx="75" cy="275"/> </g> </svg>
Definiendo la estructura para evitar la redundancia con repetición
La etiqueta g
es bastante útil para agrupar formas geométricas que tienen atributos en común, sin embargo su talón de Aquiles radica en el hecho de no poder colocar todos los atributos comunes en el elemento g
; para estos casos podemos emplear la etiqueta defs
con ayuda de la etiqueta use
como veremos a continuación.
Las etiquetas defs
y use
en conjunto, nos ayudan a definir una figura clave (mediante la etiqueta defs
) con todos sus atributos y luego podemos usar y replicar esta definición tantas veces como queramos mediante la etiqueta use
.
Específicamente hablando del ejemplo que estamos elaborando, vamos a definir un círculo con todas los atributos comunes:
<defs> <circle id="light" cx="75" r="40" /> </defs>
Y luego vamos a replicar la estructura 3 veces, una por cada luz:
<use xlink:href="#light" y="80" fill="red" /> <use xlink:href="#light" y="175" fill="yellow" /> <use xlink:href="#light" y="275" fill="green" />
Como vemos en los fragmentos de código, se emplea el atributo xlink:href
para identificar otro elemento en el documento mediante el marcado #
que permite seguir a un elemento mediante el atributo id, así que en resumen, estamos copiando la estructura de elemento cuyo id
es circle
:
<svg width="200px" height="400px"> <defs> <circle id="light" cx="75" r="40" /> </defs> <rect x="0" y="0" width="150" height="350" fill="black" stroke="gray" stroke-width="2" /> fill="blue" stroke="black" stroke-width="3" /> <g stroke="black" stroke-width="2"> <use xlink:href="#light" y="80" fill="red" /> <use xlink:href="#light" y="175" fill="yellow" /> <use xlink:href="#light" y="275" fill="green" /> </g> </svg>
Desarrollo con Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter