Símbolos animados (2)
Esta es una continuación de Símbolos animados (1)
Animando múltiples imágenes SVG
Es normal que queramos utilizar el símbolo SVG ( creado anteriormente ) varias veces en la misma página, y claro está, animarlo también.
¿Como hacerlo?
Primero el script atraviesa todo el documento en búsqueda de elementos <use>
.
var useElmts = document.getElementsByTagName("use");
A continuación escribiremos un bucle for
que recorre el array de los elementos <use>
.
for(var i=0; i<useElmts.length; i++){. . .
Dentro del bucle hay una función anónima. Se trata de una función anónima encapsulada que tiene esta sintaxis:
(function(){ alert(2 + 2); })();
Las funciónes anónimas encapsuladas se auto ejecutan de inmediato. Lo que escribimos arriba es equivalente a:
// construye la función function DosMasDos(){ alert(2 + 2); } // llama la función DosMasDos();
Lea más sobre las funciones anónimas encapsuladas en JavaScript: Explain JavaScript's encapsulated anonymous function syntax
El contenido de esta función anónima es muy parecido a lo que hemos visto anteriormente. A continuación hemos marcado con //----- el principio y el fin de la función anónima.
- var useElmts = document.getElementsByTagName("use");
- for(var i=0; i<useElmts.length; i++){
- (function () { //---------------------------------------------------
- var elId = useElmts[i].id;
- var use = document.getElementById(elId);
- // calcula el valor del centro de rotacion
- var valAttr = new Array();
- var attrRy = new Array("x", "width", "y", "height");
- for( var j = 0;j<attrRy.length; j++){
- if(use.hasAttribute(attrRy[j])){
- valAttr[j] = Number(use.getAttribute(attrRy[j]));
- }else{
- valAttr[j] = 0;}
- }
- var cx = valAttr[0] + valAttr[1]/2;
- var cy = valAttr[2] + valAttr[3]/2;
- // establece el valor del atributo transform de use
- use.setAttribute("transform","rotate(0 "+cx+" "+cy+")");
- // al hacer clic en el use ( el triangulo )
- use.addEventListener("click", function(){
- var animId = use.getElementsByTagName("animateTransform")[0].id; //transformacion1, transformacion2 ...
- var anim = document.getElementById(animId); //document.getElementById("transformacion1");
- var from = anim.getAttribute("from");
- if(from =="0 "+cx+" "+cy){
- anim.setAttribute("from", "90 "+cx+" "+cy);
- anim.setAttribute("to", "0 "+cx+" "+cy);
- }else{
- anim.setAttribute("from", "0 "+cx+" "+cy);
- anim.setAttribute("to", "90 "+cx+" "+cy);
- }
- }, false);
- }()); //--------------------------------------------------------------
- }
En el HTML tenemos 4 lienzos SVG. Primer lienzo es donde guardamos las definiciones <defs>
, en este caso el #triangulo
. Este lienzo tiene display:none
.
Los otros tres lienzos son aquellos donde utilizamos el #triangulo
con <use>
. Sabemos que el elemento <symbol>
soporta el atributo viewBox
, y por tanto una vez dibujado un símbolo podemos generar replicas de dimensiones variables. Solo hay que cambiar el valor de la anchura width
y de la altura height
del elemento <use>
.
Los elementos <use>
que muestran el #triangulo
tienen asignadas diferentes valores para la anchura width
, la altura height
y para las coordenadas x
e y
, y por tanto generan copias de tamaño diferente.
Los elementos <use>
tienen asignado un id
: "use" seguido de un número, por ejemplo id="use1"
.
También las animaciones <animateTransform>
tienen asignado un id
: "transformacion" seguido de un número, por ejemplo id ="transformacion1"
.
Esto es muy útil a la hora de manipular los elementos a través de un bucle for
.
- <svg width= "250" height= "250" viewBox= "0 0 250 250" style= "display :none;">
- <defs>
- <symbol id= "triangulo" viewBox= "0 0 250 250" >
- <polygon points= "200,125 87.5,190 87.5,60.0 200,125" style= "fill :#f00;" />
- </symbol>
- </defs>
- </svg>
- <!---->
- <svg width= "150" height= "150" viewBox= "0 0 150 150">
- <g>
- <use id= "use1" xlink:href= "#triangulo" x= "50" y= "50" width= "50" height= "50" transform= "">
- <animateTransform id= "transformacion1"
- attributeName= "transform"
- attributeType= "XML"
- type= "rotate"
- from= "" to= ""
- begin= "use1.click"
- dur= "500ms"
- fill= "freeze"/>
- </use>
- </g>
- </svg>
- <!---->
- <svg width= "150" height= "150" viewBox= "0 0 150 150">
- <g>
- <use id= "use2" xlink:href= "#triangulo" x= "60" y= "60" width= "30" height= "30" transform= "">
- <animateTransform id= "transformacion2"
- attributeName= "transform"
- attributeType= "XML"
- type= "rotate"
- from= "" to= ""
- begin= "use2.click"
- dur= "500ms"
- fill= "freeze"/>
- </use>
- </g>
- </svg>
- <!---->
- <svg width= "150" height= "150" viewBox= "0 0 150 150">
- <g>
- <use id= "use3" xlink:href= "#triangulo" x= "25" y= "25" width= "100" height= "100" transform= "">
- <animateTransform id= "transformacion3"
- attributeName= "transform"
- attributeType= "XML"
- type= "rotate"
- from= "" to= ""
- begin= "use3.click"
- dur= "500ms"
- fill= "freeze"/>
- </use>
- </g>
- </svg>
A continuación queremos crear un botón utilizando símbolos SVG animados