Texto longo, leia o resumo
- O Chrome 60 reduz o tempo de carregamento diminuindo a frequência de eventos, melhorando a consistência do tempo de frame.
- O método
getCoalescedEvents()
, introduzido no Chrome 58, fornece a mesma quantidade de informações de eventos que você já tinha.
É importante oferecer uma experiência do usuário tranquila na Web. O tempo entre o recebimento de um evento de entrada e o momento em que os recursos visuais são atualizados é importante, e geralmente fazer menos trabalho é importante. Nas últimas versões do Chrome, reduzimos a latência de entrada nesses dispositivos.
Para melhorar a fluidez e o desempenho, no Chrome 60, estamos fazendo uma mudança que faz com que esses eventos ocorram com uma frequência menor, aumentando a granularidade das informações fornecidas. Assim como quando o Jelly Bean foi lançado e trouxe o Choreographer, que alinha a entrada no Android, estamos trazendo a entrada alinhada ao frame para a Web em todas as plataformas.
Mas às vezes você precisa de mais eventos. No
Chrome 58, implementamos
um método chamado
getCoalescedEvents()
, que
permite que seu aplicativo recupere o caminho completo do ponteiro mesmo quando
ele recebe menos eventos.
Vamos falar primeiro sobre a frequência de eventos.
Como diminuir a frequência de eventos
Vamos entender alguns conceitos básicos: as telas sensíveis ao toque fornecem entrada de 60 a 120 Hz, e os mouses geralmente fornecem entrada de 100 Hz (mas podem variar até 2.000 Hz). No entanto, a taxa de atualização típica de um monitor é de 60 Hz. O que isso significa? Isso significa que recebemos entradas em uma taxa mais alta do que a taxa de atualização da tela. Vamos analisar uma linha do tempo de desempenho das ferramentas do desenvolvedor para um app de pintura de tela simples.
Na imagem abaixo, com a entrada alinhada a requestAnimationFrame()
desativada, é possível ver vários blocos de processamento por frame com um tempo de frame inconsistente.
Os pequenos blocos amarelos indicam o teste de acerto para coisas como o destino do
evento DOM, o envio do evento, a execução do JavaScript, a atualização do nó
sobreposto e possivelmente o recalculo do layout e dos estilos.
Por que estamos fazendo um trabalho extra que não causa atualizações visuais? O ideal é
não fazer nenhum trabalho que não beneficie o usuário. A partir do
Chrome 60, o pipeline de entrada vai atrasar o envio de eventos contínuos
(wheel
,
mousewheel
,
touchmove
,
pointermove
,
mousemove
) e
enviá-los logo antes do
callback requestAnimationFrame()
ocorrer. Na imagem abaixo (com o recurso ativado), você vê um tempo de frame mais
consistente e menos tempo de processamento de eventos.
Estamos realizando um experimento com esse recurso ativado nos canais Canary e Dev e descobrimos que realizamos 35% menos testes de hit, o que permite que a linha de execução principal esteja pronta para ser executada com mais frequência.
Uma observação importante que os desenvolvedores da Web precisam saber é que qualquer evento
discreto (como keydown
,
keyup
,
mouseup
,
mousedown
,
touchstart
,
touchend
) que
ocorre será enviado imediatamente com todos os eventos pendentes, preservando
a ordem relativa. Com esse recurso ativado, grande parte do trabalho é
simplificada no fluxo normal de loop de eventos, oferecendo um intervalo de entrada consistente. Isso traz eventos contínuos
em conformidade com os eventos scroll
e resize
,
que já foram simplificados no fluxo de repetição de eventos no Chrome.
Descobrimos que a grande maioria dos aplicativos que consomem esses eventos não tem uso para a frequência mais alta. O Android já alinha eventos há vários anos, então nada é novo, mas os sites podem ter eventos menos granulares em plataformas para computador. Sempre houve um problema com linhas de execução principais instáveis que causam problemas na fluidez da entrada. Isso significa que você pode notar saltos na posição sempre que o aplicativo estiver trabalhando, o que torna impossível saber como o ponteiro passou de um ponto para outro.
O método getCoalescedEvents()
Como eu disse, há raros cenários em que o aplicativo prefere saber
o caminho completo do ponteiro. Para corrigir o caso em que você vê saltos grandes e
a frequência reduzida de eventos, no Chrome 58,
lançamos uma extensão para eventos de ponteiro chamada
getCoalescedEvents()
. Confira abaixo um exemplo de como o jank na linha de execução principal é oculto do
aplicativo se você usar essa API.
Em vez de receber um único evento, você pode acessar a matriz de eventos históricos que o causou. O Android, o iOS e o Windows têm APIs muito semelhantes nos SDKs nativos, e estamos expondo uma API semelhante na Web.
Normalmente, um app de desenho pode ter desenhado um ponto observando os deslocamentos no evento:
window.addEventListener("pointermove", function(event) {
drawPoint(event.pageX, event.pageY);
});
Esse código pode ser facilmente alterado para usar a matriz 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);
}
});
Nem todas as propriedades nos eventos agrupados são preenchidas. Como os
eventos agrupados não são realmente enviados, mas apenas acompanham o percurso, eles
não são testados. Alguns campos, como currentTarget
e eventPhase
, terão
valores padrão. Chamar métodos relacionados ao envio, como stopPropagation()
ou preventDefault()
, não terá efeito no evento pai.