Texto longo, leia o resumo
- O Chrome 60 reduz a instabilidade diminuindo a frequência de eventos, melhorando a consistência do tempo para a renderização do frame.
- O método
getCoalescedEvents()
, introduzido no Chrome 58, oferece a mesma riqueza de informações de eventos que você já tinha.
Fornecer uma experiência do usuário tranquila é importante para a Web. O tempo entre o recebimento de um evento de entrada e a atualização dos recursos visuais é importante, além de fazer menos trabalho. Nas últimas versões do Chrome, diminuímos a latência de entrada nesses dispositivos.
Para suavidade e desempenho, no Chrome 60, estamos fazendo uma mudança que faz com que esses eventos ocorram em uma frequência mais baixa, aumentando a granularidade das informações fornecidas. Assim como quando o Jelly Bean foi lançado e trouxe o Choreographer, que alinha as entradas no Android, estamos trazendo as entradas alinhadas ao frame para a Web em todas as plataformas.
Mas, às vezes, você precisa de mais eventos. Portanto, no
Chrome 58, implementamos
um método chamado
getCoalescedEvents()
, que
permite que seu aplicativo recupere o caminho completo do ponteiro, mesmo enquanto
recebe menos eventos.
Vamos falar sobre a frequência de eventos primeiro.
Como diminuir a frequência de eventos
Vamos entender alguns conceitos básicos: telas sensíveis ao toque fornecem entrada de 60 a 120 Hz, e mouses enviam entradas normalmente a 100 Hz (mas podem chegar a até 2.000 Hz). No entanto, a taxa típica de atualização de um monitor é de 60 Hz. Então, o que isso realmente significa? Isso significa que as entradas são recebidas em uma taxa maior do que a atualização da tela de fato. Vamos conferir uma linha do tempo de desempenho do DevTools para um app de pintura de telas simples.
Na imagem abaixo, com a entrada alinhada requestAnimationFrame()
desativada, é
possível ver vários blocos de processamento por frame com um tempo para a renderização do frame inconsistente.
Os pequenos blocos amarelos indicam testes de hits para, por exemplo, o destino do evento DOM, o envio do evento, a execução de JavaScript, a atualização do nó flutuante e, possivelmente, o novo cálculo 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
os enviar antes da ocorrência do
requestAnimationFrame()
callback. Na imagem abaixo (com o recurso ativado), é possível ver um tempo para a renderização do frame mais
consistente e menos eventos de processamento.
Estamos realizando um experimento com esse recurso ativado nos canais Canary e Dev e descobrimos que realizamos testes de hit 35% menores, o que permite que a linha de execução principal fique pronta para ser executada com mais frequência.
Uma observação importante de que os desenvolvedores da Web precisam estar cientes é que qualquer evento
discreto (como keydown
,
keyup
,
mouseup
,
mousedown
,
touchstart
,
touchend
) que
ocorrer será enviado imediatamente com todos os eventos pendentes, preservando
a ordenação relativa. Com esse recurso ativado, grande parte do trabalho é simplificada para o fluxo de loop de eventos normal, fornecendo um intervalo de entrada consistente. Isso traz eventos contínuos
inline com eventos scroll
e resize
,
que já foram otimizados no fluxo de loop de eventos no Chrome.
Descobrimos que a grande maioria dos aplicativos que consomem esses eventos não têm utilidade para a frequência maior. O Android já alinhou eventos há vários anos, então nada é novo, mas os sites podem apresentar eventos menos granulares nas plataformas para computadores. Sempre houve um problema com linhas de execução principais instáveis, que causavam problemas na suavidade da entrada, o que significa que podem ocorrer saltos na posição sempre que o aplicativo está funcionando, o que torna impossível saber como o ponteiro passa de um ponto para outro.
Método getCoalescedEvents()
Como disse, há cenários raros em que o aplicativo prefere saber
o caminho completo do ponteiro. Portanto, para corrigir o caso em que você vê grandes saltos 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 a instabilidade na linha de execução principal fica oculta
do aplicativo se você usar essa API.
Em vez de receber um único evento, é possível acessar a matriz de eventos históricos que o causaram. 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 enviados, mas estão prontos para o passeio, eles não são testados. Alguns campos, como currentTarget
e eventPhase
, terão
os valores padrão. Chamar métodos relacionados ao envio, como stopPropagation()
ou preventDefault()
, não terá efeito no evento pai.