Cómo evitar pinturas innecesarias - Edición de GIF animado

Evitar pinturas es fundamental para lograr una velocidad de fotogramas suave y sedosa, especialmente en dispositivos móviles. Sin embargo, a veces, las pinturas aparecen en los lugares más inusuales. En este artículo, se analiza por qué los GIF animados pueden causar pinturas innecesarias y la solución notable que puedes aplicar.

Capas de encanto

Como probablemente sepas, los navegadores modernos pueden pintar grupos de elementos del DOM en “imágenes”, llamadas capas. A veces, hay una sola capa para toda la página. A veces, existen cientos o, en raras ocasiones, miles.

Cuando los elementos del DOM se agrupan en una capa y uno de los elementos cambia visualmente, terminamos teniendo que pintar no solo el elemento modificado, sino también todos los demás elementos de la capa que también se superponen con el elemento modificado. Si pintas un elemento encima de otro, los píxeles reemplazados se "perderán" para siempre. Si quieres recuperar los píxeles originales, debes volver a pintarlos.

Por lo tanto, a veces queremos aislar un elemento de los demás para que, cuando se pinte, no tengamos que volver a pintar los demás elementos que no se modificaron. Por ejemplo, cuando combinas un encabezado de página fijo con contenido desplazable, debes volver a pintar el encabezado cada vez que se desplace el contenido, así como el contenido recién visible. Si colocas el encabezado en una capa separada, el navegador puede optimizar el desplazamiento. Cuando te desplazas, el navegador puede mover las capas, probablemente con la ayuda de la GPU, y evitar tener que volver a pintar cualquiera de las capas.

Cada capa adicional aumenta el consumo de memoria y agrega sobrecarga de rendimiento. Por lo tanto, el objetivo es agrupar la página en la menor cantidad de capas posible y, al mismo tiempo, mantener un buen rendimiento.

¿Qué tiene que ver todo esto con los GIF animados?

Veamos esta imagen:

Una aplicación web dividida en cuatro capas.
Figura 1: Una aplicación web dividida en cuatro capas.

Esta es una configuración de capa potencial para una app simple. Aquí hay cuatro capas: tres de ellas (las capas 2 a 4) son elementos de la interfaz; la capa posterior es un cargador, que resulta ser un GIF animado. En el flujo normal, muestras el cargador (capa 1) mientras se carga tu app; luego, cuando todo finalice, deberías mostrar las otras capas. Pero esta es la clave: debes ocultar el GIF animado.

Pero ¿por qué tengo que ocultarla?

Buena pregunta. En un mundo ideal, el navegador simplemente comprobaría la visibilidad del GIF por ti y evitaría pintar automáticamente. Lamentablemente, comprobar si el GIF animado está oscurecido o visible en la pantalla suele ser más costoso que simplemente pintarlo, por lo que se pinta.

En el mejor de los casos, el GIF está en su propia capa y el navegador solo tiene que pintarlo y subirlo a la GPU. Sin embargo, en el peor de los casos, todos tus elementos podrían estar agrupados en una sola capa y el navegador tendrá que volver a pintar todos los elementos. Y cuando ya está listo, debe subir todo a la GPU. Todo esto es trabajo para cada fotograma del GIF, a pesar de que el usuario ni siquiera puede ver el GIF.

En las computadoras de escritorio, es probable que puedas olvidarte de este tipo de comportamiento de pintura porque las CPU y las GPU son más potentes y hay mucho ancho de banda para transferir datos entre ambas. Sin embargo, en dispositivos móviles, la pintura es extremadamente costosa, por lo que debes tener mucho cuidado.

¿A qué navegadores afecta?

Como suele ser el caso, los comportamientos difieren entre los navegadores. Hoy en día, Chrome, Safari y Opera vuelven a pintar, incluso si el GIF se ve oscurecido. Firefox, por otro lado, detecta que el GIF está oscurecido y no es necesario volver a pintarlo. Internet Explorer sigue siendo una especie de caja negra, e incluso en IE11, dado que las herramientas de F12 aún se están desarrollando, no hay indicios de si se está realizando un rediseño.

¿Cómo puedo saber si tengo este problema?

La forma más sencilla es usar "Mostrar rectángulos de pintura" en las Herramientas para desarrolladores de Chrome. Carga Herramientas para desarrolladores, presiona el engranaje en la esquina inferior derecha (Ícono de engranaje) y elige Mostrar rectángulos de pintura en la sección Renderización.

Cómo habilitar la opción Mostrar rectángulos de pintura en las Herramientas para desarrolladores de Chrome
Figura 2: Habilitación de Mostrar rectángulos de pintura en las Herramientas para desarrolladores de Chrome

Ahora, todo lo que necesitas hacer es buscar un rectángulo rojo como este:

Mostrar rectángulos de pintura de Herramientas para desarrolladores sugiere problemas con GIF animados con un rectángulo rojo.
Figura 3: Mostrar rectángulos de pintura de Herramientas para desarrolladores sugiere problemas con GIF animados con un rectángulo rojo.

El pequeño cuadro rojo de la pantalla muestra que Chrome está volviendo a pintar algo. Sabes que hay un GIF de cargador escondido detrás de los otros elementos, por lo que cuando veas un cuadro rojo como este, debes ocultar los elementos visibles y verificar si dejaste el GIF animado que da vueltas. Si lo necesitas, debes implementar CSS o JavaScript para aplicar display: none o visibility: hidden a ellos o a su elemento superior. Por supuesto, si es solo una imagen de fondo, debes asegurarte de quitarla.

Si quieres ver un ejemplo de este comportamiento en un sitio publicado, consulta Allegro, donde la imagen de cada producto tiene un GIF de cargador que está oculto en lugar de estar explícitamente oculto.

Conclusión

Si logras los 60 FPS, solo deberás hacer lo necesario para procesar la página. Quitar el exceso de pintura es un paso fundamental para lograr este objetivo. Los GIF animados que se dejan en ejecución pueden activar pinturas innecesarias, algo que puedes encontrar y depurar fácilmente con la herramienta Mostrar rectángulos de pintura de Herramientas para desarrolladores.

Bueno, no dejaste que ese GIF animado de cargador de gatitos se ejecutara para siempre, ¿verdad?