A modo de resumen
- Chrome 60 reduce los bloqueos disminuyendo la frecuencia de eventos, lo que mejora la coherencia del tiempo de fotogramas.
- El método
getCoalescedEvents()
, que se introdujo en Chrome 58, proporciona la misma gran cantidad de información de eventos que siempre has tenido.
Proporcionar una experiencia del usuario fluida es importante para la Web. El tiempo entre recibir un evento de entrada y el momento en que las imágenes se actualizan es importante, y, por lo general, es importante hacer menos trabajo. En las últimas versiones de Chrome, logramos reducir la latencia de entrada en estos dispositivos.
Para mejorar la fluidez y el rendimiento, en Chrome 60, realizaremos un cambio que hará que estos eventos ocurran con una frecuencia menor y, al mismo tiempo, aumentará el nivel de detalle de la información proporcionada. Al igual que cuando se lanzó Jelly Bean y se introdujo Choreographer, que alinea la entrada en Android, llevaremos la entrada alineada con el fotograma a la Web en todas las plataformas.
Sin embargo, a veces necesitas más eventos. Por lo tanto, en Chrome 58, implementamos un método llamado getCoalescedEvents()
, que permite que tu aplicación recupere la ruta de acceso completa del puntero incluso mientras recibe menos eventos.
Primero, hablemos de la frecuencia de los eventos.
Disminuye la frecuencia de los eventos
Veamos algunos conceptos básicos: las pantallas táctiles proporcionan entradas de 60 a 120 Hz, y los mouses suelen proporcionar entradas de 100 Hz (pero pueden ser de hasta 2000 Hz). Sin embargo, la frecuencia de actualización típica de un monitor es de 60 Hz. ¿Qué significa eso? Esto significa que recibimos entradas a una velocidad más alta que la que realmente actualizamos la pantalla. Veamos un cronograma de rendimiento de las herramientas para desarrolladores para una app de pintura de lienzo simple.
En la siguiente imagen, con la entrada alineada con requestAnimationFrame()
inhabilitada, puedes ver varios bloques de procesamiento por fotograma con un tiempo de fotograma incoherente.
Los pequeños bloques amarillos indican pruebas de hit para elementos como el objetivo del
evento DOM, el envío del evento, la ejecución de JavaScript, la actualización del nodo sobre el que se hace
hover y, posiblemente, el nuevo cálculo del diseño y los estilos.
Entonces, ¿por qué hacemos un trabajo adicional que no genera ninguna actualización visual? Lo ideal es que no queramos hacer ningún trabajo que, en última instancia, no beneficie al usuario. A partir de Chrome 60, la canalización de entrada retrasará el envío de eventos continuos (wheel
, mousewheel
, touchmove
, pointermove
, mousemove
) y los enviará justo antes de que se produzca la devolución de llamada de requestAnimationFrame()
. En la siguiente imagen (con la función habilitada), se muestra un tiempo de fotogramas más uniforme y menos tiempo de procesamiento de eventos.
Ejecutamos un experimento con esta función habilitada en los canales Canary y Dev, y descubrimos que realizamos un 35% menos de pruebas de hit, lo que permite que el subproceso principal esté listo para ejecutarse con más frecuencia.
Una nota importante que los desarrolladores web deben tener en cuenta es que cualquier evento discreto (como keydown
, keyup
, mouseup
, mousedown
, touchstart
y touchend
) que ocurra se enviará de inmediato junto con cualquier evento pendiente, preservando el orden relativo. Con esta función habilitada, gran parte del trabajo se optimiza en el flujo normal del bucle de eventos, lo que proporciona un intervalo de entrada coherente. Esto alinea los eventos continuos con los eventos scroll
y resize
, que ya se optimizaron en el flujo del bucle de eventos en Chrome.
Descubrimos que la gran mayoría de las aplicaciones que consumen esos eventos no tienen uso para la frecuencia más alta. Android ya alineó los eventos durante varios años, por lo que no hay nada nuevo, pero es posible que los sitios experimenten eventos menos detallados en plataformas de computadoras de escritorio. Siempre hubo un problema con los subprocesos principales inestables que causaban interrupciones en la fluidez de la entrada, lo que significa que es posible que veas saltos de posición cada vez que la aplicación esté en funcionamiento, lo que hace imposible saber cómo el puntero pasó de un lugar a otro.
El método getCoalescedEvents()
Como dije, hay casos poco frecuentes en los que la aplicación prefiere conocer la ruta completa del puntero. Por lo tanto, para corregir el caso en el que ves saltos grandes y la frecuencia reducida de eventos, en Chrome 58, lanzamos una extensión para eventos del puntero llamada getCoalescedEvents()
. A continuación, se muestra un ejemplo de cómo se oculta el bloqueo en el subproceso principal a la aplicación si usas esta API.
En lugar de recibir un solo evento, puedes acceder al array de eventos históricos que lo causaron. Android, iOS y Windows tienen APIs muy similares en sus SDKs nativos, y exponemos una API similar a la Web.
Por lo general, una app de dibujo puede haber dibujado un punto mirando los desplazamientos en el evento:
window.addEventListener("pointermove", function(event) {
drawPoint(event.pageX, event.pageY);
});
Este código se puede cambiar fácilmente para usar el array de eventos:
window.addEventListener("pointermove", function(event) {
var events = 'getCoalescedEvents' in event ? event.getCoalescedEvents() : [event];
for (let e of events) {
drawPoint(e.pageX, e.pageY);
}
});
Ten en cuenta que no se propagan todas las propiedades de los eventos fusionados. Dado que los eventos fusionados no se despachan, sino que solo están presentes, no se prueban los hits. Algunos campos, como currentTarget
y eventPhase
, tendrán sus valores predeterminados. Llamar a métodos relacionados con el envío, como stopPropagation()
o preventDefault()
, no tendrá ningún efecto en el evento superior.