2011-06-28 7 views
5

Estoy usando SVG para gráficos en una aplicación web AJAX. Cuando se reciben los datos iniciales, me gustaría animar los elementos del gráfico (como barras) desde los valores predeterminados de 0 hasta el nuevo valor de datos. Si el usuario selecciona un nuevo conjunto de datos, solicito nuevos datos del servidor y luego deseo animar la barra desde el valor anterior al nuevo.Cambia dinámicamente los valores de animación SVG al usar fill = "freeze"

<rect x="0" y="0" width="1px" height="20px" fill="red"> 
    <animate id="anim" attributeName="width" attributeType="XML" 
     begin="indefinite" from="0" to="100px" dur="0.8s" fill="remove"/> 
</rect> 

se recibe Cada dato de tiempo, me puse la from y to atributos y llamar beginElement().

Si configuro fill="remove" en la animación SVG, la barra se anima correctamente cada vez que se carga un nuevo conjunto de datos, pero, por supuesto, entre las animaciones, la barra vuelve a su ancho predeterminado.

Configuración width.baseVal.value para establecer un nuevo valor base antes o después de llamar al beginElement() provoca un parpadeo muy desagradable.

Así que traté de usar fill="freeze" para que la barra mantenga su ancho al final de cada animación. El problema es que la primera animación funciona, pero cada llamada posterior a beginElement() devuelve la barra a su ancho predeterminado de inmediato y la animación deja de funcionar.

Estoy probando en Chrome 12.0. Aquí hay una muestra para ver cómo se rompe la animación al usar el congelamiento.

http://jsfiddle.net/4ws9W/

<!DOCTYPE html> 
<html> 
    <head><title>Test SVG animation</title></head> 

    <body> 
    <svg width="200px" height="20px" xmlns="http://www.w3.org/2000/svg" version="1.1"> 
     <rect x="0" y="10px" width="200px" height="2px"/> 

     <rect x="0" y="0" width="1px" height="20px" fill="red"> 
     <animate id="anim" attributeName="width" attributeType="XML" begin="indefinite" from="0" to="100px" dur="1.3s" fill="freeze"/> 
     </rect> 

     parent.anim = document.getElementById('anim'); 

    </svg> 

    <br/> 
    <a href="javascript:anim.beginElement();">anim.beginElement();</a> 
    <br/> 
    <a href="javascript:anim.endElement();">anim.endElement();</a> 
    <br/> 

    <br/> 
    <a href="javascript:anim.setAttribute('to', '50px');">anim.setAttribute('to', '50px');</a> 
    <br/> 
    <a href="javascript:anim.setAttribute('to', '150px');">anim.setAttribute('to', '150px');</a> 
    <br/> 

    <br/> 
    <a href="javascript:anim.setAttribute('fill', 'remove');">anim.setAttribute('fill', 'remove');</a> 
    <br/> 
    <a href="javascript:anim.setAttribute('fill', 'freeze');">anim.setAttribute('fill', 'freeze');</a> 
    <br/> 

    </body> 
</html> 

¿Cómo puedo animar el ancho de una barra, haga que sea mantener el nuevo ancho, y luego animar repetidamente a nuevos valores a medida que llegan?

+0

¿Encontró una solución para esto? Tengo un problema similar al continuar animando los cambios de color usando fill = freeze. – ssawchenko

Respuesta

1

Puede llamar al método suspendRedraw en los elementos necesarios para evitar el parpadeo. HTH

+0

Gracias, @Spadar. Responderé más una vez que tenga la oportunidad de probar esto. –

+0

Oh, y tienes que llamar unsuspndRedraw luego. Sin embargo, no estoy seguro de la compatibilidad del navegador, pero esto funcionó en Opera. –

0

Solo una idea: configure los atributos 'begin' para que sean la cantidad actual de segundos transcurridos desde que se cargó la página.
Un poco como así:

function seconds_elapsed()  { 
    var date_now = new Date(); 
    var time_now = date_now.getTime(); 
    var time_diff = time_now - startTime; 
    var seconds_elapsed = Math.floor (time_diff/1000); 
    return (seconds_elapsed); 
} 

y/o añadir nuevas animaciones con .appendChild() en lugar de jugar con los valores existentes.

1

Creo que cuando actualice el siguiente valor 'to', actualice el valor actual 'to' al atributo width del objeto rectángulo, así como al atributo 'from' de la animación. Mientras lo actualizas, asegúrate de configurar el relleno-> eliminar y luego de cambiar el valor del atributo revertir el relleno-> congelar. ver si el código a continuación funciona.

<!DOCTYPE html> 
    <html> 
    <head><title>Test SVG animation</title> 
    <script type='text/javascript'> 
    var animNode = 0; 
    function OnEndHandler(evt) 
    { 
     if(!animNode) 
     animNode = evt.target;  
     var previousToValue = animNode.getAttribute('to'); 
     animNode.parentNode.setAttribute('width', previousToValue); 
     animNode.setAttribute('from', previousToValue);  
    } 
    function OnBtnHandler(event) 
    { 
     if(!animNode) 
      animNode = document.querySelector('#anim'); 
    if(event.target.id == 'nextBtn') 
    { 
     animNode.setAttribute('fill', 'remove'); 
     animNode.setAttribute('to', '150px'); 
     animNode.setAttribute('fill', 'freeze'); 
     animNode.beginElement(); 
    } 
    else if(event.target.id == 'startBtn') 
    { 
     animNode.setAttribute('to', '50px');  
     animNode.beginElement(); 
    } 
    } 

    </script> 
    </head> 

    <body> 
    <input id= 'startBtn' type='button' value='StartBar' onclick='OnBtnHandler(event)' /> 
     <input id='nextBtn' type='button' value='NextBar' onclick='OnBtnHandler(event)'  />  
    <svg width="200px" height="20px" xmlns="http://www.w3.org/2000/svg" version="1.1"> 
     <rect x="0" y="10px" width="200px" height="2px"/> 
     <rect x="0" y="0" width="1px" height="20px" fill="red"> 
     <animate id="anim" attributeName="width" attributeType="XML" begin="indefinite" from="0" to="100px" dur="1.3s" fill="freeze" onend='OnEndHandler(evt)' /> 
     </rect> 
    </svg> 

    <br/> 
    <a href="javascript:anim.beginElement();">anim.beginElement();</a> 
    <br/> 
    <a href="javascript:anim.endElement();">anim.endElement();</a> 
    <br/> 

    <br/> 
    <a href="javascript:anim.setAttribute('to', '50px');">anim.setAttribute('to', '50px');</a> 
    <br/> 
    <a href="javascript:anim.setAttribute('to', '150px');">anim.setAttribute('to', '150px'); </a> 
    <br/> 

    <br/> 
    <a href="javascript:anim.setAttribute('fill', 'remove');">anim.setAttribute('fill', 'remove');</a> 
    <br/> 
    <a href="javascript:anim.setAttribute('fill', 'freeze');">anim.setAttribute('fill', 'freeze');</a> 
    <br/> 

    </body> 
</html> 
Cuestiones relacionadas