2012-08-12 15 views
15

Como experimento, estoy tratando de replicar la funcionalidad Sprite de AS3 en JavaScript sin usar el objeto canvas. Pensé que el uso de divs absolutamente posicionados y la manipulación de sus propiedades CSS no sería pan comido, sin embargo, en Chrome, la animación introduce artefactos extraños (aparentemente debido a problemas de redibujado).Animar un DIV con JavaScript representa artefactos en Chrome

¿No puedo encontrar lo que estoy haciendo mal? El código es, de hecho, bastante simple. He aquí algunos puntos que he intentado que no ayuda: (. A diferencia de posición absoluta)

  • El uso de divs posicionadas relativamente
  • Usando márgenes
  • Anexión (en contraposición al principio & propiedades izquierda). objetos directamente en el cuerpo (en contraposición a anexar a un contenedor div.)
  • el uso de setTimeout (en contraposición a requestAnimationFrame)

Se puede ver un violín simplificada aquí: http://jsfiddle.net/BVJYJ/2/

EDIT: http://jsfiddle.net/BVJYJ/4/

Y aquí se puede ver los artefactos en mi navegador:

The artifacts in Chrome

Esto puede ser un error en mi programa de instalación (Windows 7 64 bits, Chrome 21.0.1180.75) Ningún otro navegador muestra este comportamiento. Agradecería mucho si alguien pudiera comentar sobre lo que podría estar haciendo mal. Tengo más curiosidad acerca de la razón detrás de esto en lugar de una solución alternativa por cierto. Dicho eso, todas las explicaciones son bienvenidas. :)

EDITAR: Hubo un error en el código de muestra que dio lugar al uso de setTimeout incluso cuando tenía la impresión de que se utilizaba RAF. requestAnimationFrame resuelve el problema con la transformación básica, pero el problema persiste con las transformaciones CSS, como la rotación.

The artifacts in Chrome with rotation transformation.

+0

Parece que esto se informó como un error para chrome/chromium> 21 http://code.google .com/p/chromium/issues/detail? id = 140501 – erkmene

+0

esto parece ser una solución en Chrome 24? – gman

Respuesta

28

he tenido el mismo problema con mi plugin de liteAccordion. Se puede solucionar estableciendo la visibilidad de la cara posterior oculta en el elemento que está animando, como puede ver aquí: http://jsfiddle.net/ZPQBp/1/

+0

Esto es bastante interesante. No estaba al tanto de esa propiedad, realmente evita que ocurran los artefactos. Muchas gracias. – erkmene

+5

La línea en CSS es: '-webkit-backface-visibility: hidden;' –

3

Algunas investigaciones muestran que setTimeout podría causar problemas debido a diversas razones. Realmente debería usar requestAnimationFrame:

Los temporizadores no son precisos al milisegundo. Éstos son algunos temporizador común resoluciones 1:

  • Internet Explorer 8 y anteriores tienen una resolución del temporizador de 15.625ms
  • Internet Explorer 9 y posterior tienen una resolución del temporizador de 4 ms. Firefox
  • y Safari tienen una resolución de temporizador de ~ 10ms.
  • Chrome tiene una resolución de 4 ms.

Internet Explorer anteriores a la versión 9 tiene una resolución del temporizador de 15.625 ms 1, por lo que cualquier valor entre 0 y 15 podrían ser 0 o 15, pero nada más. Internet Explorer 9 mejoró la resolución del temporizador a 4 ms, , pero aún no es muy específico cuando se trata de animaciones.

La resolución del temporizador de Chrome es de 4 ms, mientras que la de Firefox y Safari es de 10 ms. Por lo tanto, incluso si configura el intervalo para una visualización óptima, seguirá siendo solo acercándose al tiempo que desee.

Referencia: http://www.nczonline.net/blog/2011/05/03/better-javascript-animations-with-requestanimationframe/

también

setTimeout no tiene en cuenta lo que esté sucediendo en el navegador . La página podría estar oculta detrás de una pestaña, acaparando su CPU cuando no es necesario, o la propia animación podría haberse desplazado fuera de la página haciendo innecesaria la llamada de actualización. Chrome hace throttle setInterval y setTimeout a 1 fps en pestañas ocultas, pero este no es confiable para todos los navegadores.

En segundo lugar, setTimeout solo actualiza la pantalla cuando quiere, no cuando la computadora puede hacerlo. Eso significa que su pobre navegador tiene que hacer malabarismos redibujando la animación mientras se vuelve a dibujar toda la pantalla, y si la velocidad de cuadros de la animación no está sincronizada con el redibujado de su pantalla, podría tomar más poder de procesamiento. Eso significa mayor uso de CPU y el ventilador de su computadora pateando, o drenando la batería en su dispositivo móvil. Nicolas Zakas hace un excelente trabajo explicando el impacto que tiene la resolución del temporizador en la animación en un relacionado article.

Referencia: http://creativejs.com/resources/requestanimationframe/

+0

Gracias por su respuesta. Hubo un error en el código que causó una alternativa a setTimeOut. Puede ver en la pregunta actualizada que el problema continúa cuando se usa RAF con transformaciones CSS. ¿Tienes alguna idea de cómo se puede resolver eso? – erkmene

1

Tiene algo que ver con subpixel positioning. Si redondear al píxel más cercano que no verá los errores de renderizado:

thisRef.block.style.left = Math.round((x + (mouseX - ox - x) * .125)) + "px"; 
thisRef.block.style.top = Math.round((y + (mouseY - oy - y) * .125)) + "px"; 
+0

Gracias por la sugerencia. Como puede ver en la pregunta actualizada, el problema persiste con las transformaciones de CSS, incluso cuando se aplica el redondeo. (Probablemente porque la transformación resultante requerirá subpíxeles para representar.) Http://jsfiddle.net/BVJYJ/5/ – erkmene

Cuestiones relacionadas