Símbolos animados (3)
Esta es una continuación de Símbolos animados (2)
Queremos utilizar el símbolo animado para construir un botón, y queremos que la animación pase cuando hacemos clic en el botón.
Esto está muy fácil. Sencillamente dibujamos el botón, un rectángulo <rect>
con bordes redondeados ( rx="10" ry="10"
), y le damos un id
, "rect1" - por ejemplo.
<rect id="rect1" x="0" y="0" height="60" width="150" rx="10" ry="10" style="stroke:#ccc; fill: #fff"/>
Utilizamos el elemento <text>
para escribir algo como "botón" - para que se sepa que es un botón.
<text x="20" y="40" fill="none" stroke="#ccc" style="font-size: 30px;">Botón</text>
También cambiamos el valor del atributo begin
de <animateTransform>
de begin="click"
a begin="rect1.click"
. Esto hará que la animación empiece al hacer clic en el rectángulo #rect1
.
<use id="use1" xlink:href="#triangulo" x="100" y="5" width="50" height="50" transform="">
<animateTransform id="transformacion1"
attributeName="transform"
attributeType="XML"
type="rotate"
from="" to=""
begin="rect1.click"
dur="500ms"
fill="freeze"/>
</use>
Hacemos lo mismo en el JavaScript.
// al hacer clic en el rectángulo
var rect = document.getElementById("rect"+(i+1));
rect.addEventListener("click", function(){. . .
Pero el rectángulo está debajo del triangulo y del texto. Esto bloqueará la animación al hacer clic en uno de estos dos elementos. Para que esto no pase utilizamos pointer-events: none
, para inhabilitar los eventos del ratón encima de estos elementos.
En este momento la propiedad pointer-events está bien soportada en los principales navegadores.
Lea este articulo CSS-tricks: pointer-events
<rect id="rect1" .... style="pointer-events:none" style="stroke:#ccc; fill: #fff"/> <text ..... style="font-size: 30px; pointer-events:none">Botón</text>
Haz algo
Además de la animación – que es una cosa muy bonita – queremos que pase algo al hacer clic en el botón, que por esto están hechos los botones. En nuestro caso este "algo" será muy poca cosa:
function hazAlgo(){alert("haz algo");}
Queremos llamar la función hazAlgo()
con el primer clic en el botón. El truco consiste en utilizar el método setTimeout()
, ya que se trata de un proceso independiente que no interfiere y no bloquea los demás procesos que pasan en la página.
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);
setTimeout(function () {hazAlgo()}, 10);
}
Lea más acerca de SetTimeout & setInterval
Veamos cómo queda
- <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 :#ccc;" />
- </symbol>
- </defs>
- </svg>
- <svg width= "150" height= "60" viewBox= "0 0 150 60">
- <rect id= "rect1" x= "0" y= "0" height= "60" width= "150" rx= "10" ry= "10" style= "stroke :#ccc; fill: #333"/>
- <text x= "20" y= "40" fill= "none" stroke= "#ccc" style= "font-size: 30px; pointer-events:none">Botón</text>
- <use id= "use1" xlink:href= "#triangulo" x= "100" y= "5" width= "50" height= "50" style= "pointer-events:none" transform= "">
- <animateTransform id= "transformacion1"
- attributeName= "transform"
- attributeType= "XML"
- type= "rotate"
- from= "" to= ""
- begin= "rect1.click"
- dur= "500ms"
- fill= "freeze"/>
- </use>
- </svg>
- function hazAlgo(){alert("haz algo");}
- 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 rectangulo
- var rect = document.getElementById("rect"+(i+1));
- rect.addEventListener("click", function(){
- var animId = use.getElementsByTagName("animateTransform")[0].id;
- var anim = document.getElementById(animId);
- var from = anim.getAttribute("from");
- // establece el valor de los atributos FOR y TO
- 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);
- // llama la función hazAlgo
- setTimeout(function () {hazAlgo()}, 10);
- }
- }, false);
- }()); //--------------------------------------------------------------
- }