Aceleración predeterminada del desplazamiento de la rueda

Sahel Sharify
Sahel Sharify

Para mejorar el rendimiento de desplazamiento o zoom de wheel, se recomienda a los desarrolladores registrar los objetos de escucha de eventos wheel y mousewheel como pasivos pasando la opción {passive: true} a addEventListener(). Si registras los objetos de escucha de eventos como pasivos, le indicas al navegador que los objetos de escucha de la rueda no llamarán a preventDefault() y que el navegador puede realizar el desplazamiento y el zoom de forma segura sin bloquear los objetos de escucha.

El problema es que, con mayor frecuencia, los objetos de escucha de eventos de la rueda son conceptualmente pasivos (no llaman a preventDefault()), pero no se especifican explícitamente como tales, lo que requiere que el navegador espere a que finalice el manejo de eventos de JS antes de comenzar a desplazarse o acercar, aunque no sea necesario esperar. En Chrome 56, solucionamos este problema para touchstart y touchmove, y ese cambio se adoptó más tarde en Safari y Firefox. Como puedes ver en el video de demostración que hicimos en ese momento, dejar el comportamiento como estaba produjo una demora notable en la respuesta del desplazamiento. Ahora, en Chrome 73, aplicamos la misma intervención a los eventos wheel y mousewheel.

La intervención

Nuestro objetivo con este cambio es reducir el tiempo que se tarda en actualizar la pantalla después de que el usuario comienza a desplazarse con la rueda o el panel táctil sin que los desarrolladores deban cambiar el código. Nuestras métricas muestran que el 75% de los objetos de escucha de eventos wheel y mousewheel registrados en destinos raíz (ventana, documento o cuerpo) no especifican ningún valor para la opción pasiva y más del 98% de esos objetos de escucha no llaman a preventDefault(). En Chrome 73, cambiaremos los objetos de escucha wheel y mousewheel registrados en los destinos raíz (ventana, documento o cuerpo) para que sean pasivos de forma predeterminada. Esto significa que un objeto de escucha de eventos como el siguiente:

window.addEventListener("wheel", func);

se convierte en lo siguiente:

window.addEventListener("wheel", func, {passive: true});

Además, se ignorará la llamada a preventDefault() dentro del objeto de escucha con la siguiente advertencia de DevTools:

[Intervention] Unable to preventDefault inside passive event listener due
to target being treated as passive. See https://www.chromestatus.com/features/6662647093133312

Orientación y fallas

En la gran mayoría de los casos, no se observará ningún daño. Solo en casos excepcionales (menos del 0.3% de las páginas según nuestras métricas), es posible que se produzcan desplazamientos o zoom no deseados debido a que se ignora la llamada a preventDefault() dentro de los objetos de escucha que se consideran pasivos de forma predeterminada. Tu aplicación puede determinar si puede estar ocurriendo en el entorno real si comprueba si llamar a preventDefault() tuvo algún efecto a través de la propiedad defaultPrevented. La solución para los casos afectados es relativamente fácil: pasa {passive: false} a addEventListener() para anular el comportamiento predeterminado y conservar el objeto de escucha de eventos como bloqueo.