Símbolos animados (3)

facebook-svg gplus-svg twitter-svg

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.

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"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&oacute;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);
  • }()); //--------------------------------------------------------------
  • }
Botón