2009-07-30 15 views
5

He creado una secuencia de comandos que desvanece el color de fondo de un elemento. Uso setTimeout() para hacer un cambio incremental al color cada 5 ms. La secuencia de comandos funciona muy bien si solo estoy desvaneciendo el color de fondo de una cosa a la vez, pero si tengo, digamos, 50 elementos me estoy desvaneciendo a la vez, la velocidad es mucho más lenta que 5 ms debido a todo el setTimeout() simultáneo corriendo al mismo tiempo. Un desvanecimiento que normalmente debería ejecutarse en 1 segundo, por ejemplo, puede tomar 30 segundos si me estoy desvaneciendo 50 elementos a la vez.JavaScript setTimeout() se ralentiza bajo mucha carga

¿Alguna idea de cómo puedo superar esto?

Aquí está la secuencia de comandos en caso de que alguien tiene una ideas de:

function fadeBackground(elementId, start, end, time) { 
    var iterations = Math.round(time/5); 

    var step = new Array(3); 

    step[0] = (end[0] - start[0])/iterations; 
    step[1] = (end[1] - start[1])/iterations; 
    step[2] = (end[2] - start[2])/iterations; 

    stepFade(elementId, start, step, end, iterations); 
} 

function stepFade(elementId, cur, step, end, iterationsLeft) { 
    iterationsLeft--; 

    document.getElementById(elementId).style.backgroundColor 
     = "rgb(" + cur[0] + "," + cur[1] + "," + cur[2] + ")"; 

    cur[0] = Math.round(end[0] - step[0] * iterationsLeft); 
    cur[1] = Math.round(end[1] - step[1] * iterationsLeft); 
    cur[2] = Math.round(end[2] - step[2] * iterationsLeft); 

    if (iterationsLeft > 1) { 
     setTimeout(function() { 
      stepFade(elementId, cur, step, end, iterationsLeft); 
     }, 5); 
    } 
    else { 
     document.getElementById(elementId).style.backgroundColor 
      = "rgb(" + end[0] + "," + end[1] + "," + end[2] + ")"; 
    } 
} 

Es utilizado como esto:

fadeBackground("myList", [98,180,232], [255,255,255], 1000); 

Respuesta

11

Aquí es un article de Google, donde el autor analiza su trabajo en temporizadores para Gmail. Descubrieron que tener un solo temporizador de alta frecuencia era más rápido que utilizar varios temporizadores si tenían un uso del temporizador pesado y rápido.

Puede tener un temporizador que dispare cada 5 ms y agregar todos sus elementos que deban atenuarse a una estructura de datos que rastree su ubicación en el proceso de desvanecimiento. Entonces, su único temporizador puede mirar a través de esa lista y realizar el siguiente fundido para cada elemento cada vez que se activa.

Por otro lado, ¿ha intentado utilizar una biblioteca como Mootools o JQuery en lugar de rodar su propio marco de animación? Sus desarrolladores han dedicado mucho esfuerzo a la optimización de este tipo de operaciones.

+0

Estaba pensando que un temporizador podría ser el camino a seguir, pero temía tener que implementar el cambio. :) De hecho, decidí lanzar el mío porque estaba usando jQuery para animar() y no se desvaneció un 10% del tiempo. Desafortunadamente, esa es una tasa de error inaceptable. Veré el artículo. ¡Muchas gracias! – core

+0

Heh. Stackoverflow también tiene ese problema de "no se puede animar". – Nosredna

4

En primer lugar, su secuencia de comandos no tiene en cuenta que el tiempo de espera mínimo suele ser de 10-15 ms dependiendo de un navegador. Usted puede ver my post on this topic. En el interior encontrará una tabla para navegadores populares y un enlace al programa que la mide, para que pueda verificar la reclamación usted mismo. Lamento decirlo, pero las iteraciones cada 5 ms son una ilusión.

En segundo lugar, los temporizadores no son interrupciones. No hay magia en ellos — que no pueden interrumpir lo que se está ejecutando en el navegador y ejecutar su carga útil. En su lugar, se aplazarán hasta que el código de ejecución finalice y el navegador recupere el control y la capacidad de ejecutar temporizadores. Los elementos de desvanecimiento 50 toman tiempo, y apuesto a que son más de 5 ms, especialmente si se tiene en cuenta todo el modelo diferido del navegador: actualiza DOM, y el navegador actualizará su representación visual & hellip; en algún punto en el tiempo.

Quiero terminar con una nota positiva:

  • En lugar de desvanecimiento de 50 elementos individuales, tratar de agruparlos y se desvanecen sus padres — puede ser más rápido.
  • Sea más creativo en la interfaz de usuario. Intente encontrar una solución que no requiera desvanecer una gran cantidad de elementos independientes a la vez.
  • Siempre verifique que las suposiciones de fondo sean correctas antes de diseñar alrededor de ellas.
  • Si puede, intente orientarse a navegadores modernos. Desde mi experiencia personal, Google Chrome es muy bueno con los temporizadores, y su motor JavaScript (V8) es extremadamente rápido.
Cuestiones relacionadas