Um desenvolvedor que cria detecção de pinça com dois dedos usando ouvintes TouchEvent vai entregar código que funciona perfeitamente em um celular Android e silenciosamente não faz nada em um laptop Windows. A razão é arquitetural, não um bug do navegador: um trackpad de desktop não dispara TouchEvent de jeito nenhum. Saber quais eventos cada dispositivo de entrada realmente produz — e por quê — é o pré-requisito para escrever código de gestos que funcione em várias categorias de dispositivos.
O que são PointerEvent e TouchEvent
TouchEvent é a API mais antiga das duas. Introduzida para lidar com entrada por toque em telas sensíveis ao toque móveis, ela entrega uma lista de contatos ativos (touches, targetTouches, changedTouches) através de eventos chamados touchstart, touchmove, touchend e touchcancel. Cada entrada nessas listas é um objeto Touch com suas próprias coordenadas e identificador. A API foi projetada especificamente para telas sensíveis ao toque, e essa origem fica clara: ela não tem conceito de mouse, caneta ou trackpad.
PointerEvent é a substituição unificada do W3C, lançada primeiro no Internet Explorer 11 e agora parte de todos os principais navegadores. Ela lida com mouse, caneta e toque através de uma única família de eventos — pointerdown, pointermove, pointerup, pointercancel — e expõe uma propriedade pointerType em cada evento que nomeia a fonte: "mouse", "pen" ou "touch". A documentação MDN de Pointer Events descreve o modelo completo; a especificação W3C é mantida em w3c.github.io/pointerevents.
O que um trackpad de desktop realmente dispara
Esta é a parte que surpreende a maioria dos desenvolvedores: um trackpad de laptop em um sistema operacional desktop não dispara TouchEvent, e não produz PointerEvent com pointerType: "touch". Ele dispara:
- PointerEvent com
pointerType: "mouse"— movimento e cliques de contato único chegam como eventos comuns de ponteiro-mouse. O navegador não consegue dizer pelo evento sozinho se o dispositivo físico de entrada foi um mouse físico ou um trackpad. - WheelEvent — rolagem com dois dedos no trackpad produz um evento
wheel, exatamente como a roda de rolagem de um mouse. As propriedadesdeltaXedeltaYreportam as quantidades de rolagem. - WheelEvent com
ctrlKey: true— o sistema operacional converte o gesto de pinça para zoom do trackpad em um eventowheelcom a flagctrlKeyativada. Este é o sinal padrão entre navegadores para zoom acionado por trackpad. Páginas web que interceptamctrl+wheelpara implementar comportamento customizado de zoom estão usando exatamente essa convenção.
Telas sensíveis ao toque, por outro lado, disparam PointerEvent com pointerType: "touch" — e em navegadores que ainda mantêm a API legada, também TouchEvent. Dois dedos em uma tela sensível ao toque produzem dois eventos pointerdown simultâneos, cada um com um pointerId distinto, que o código web pode usar diretamente para calcular a escala da pinça comparando a distância entre os ponteiros.
Por que a distinção importa para código de gestos
As consequências práticas se dividem em três padrões:
- Pinça com dois dedos em tela sensível ao toque — detectável rastreando dois eventos
pointerdownsimultâneos (ou duas entradas emTouchEvent.touches) e calculando a distância entre eles ao longo de eventospointermove. Esse padrão funciona em dispositivos móveis, mas não produz nada útil em um trackpad de desktop, porque o trackpad nunca envia dois contatos simultâneos para o navegador. - Pinça para zoom no trackpad — detectável apenas via evento
wheelcomctrlKey === true. Não é necessário nem possível fazer cálculo com dois ponteiros. O sistema operacional já converteu o gesto de dois dedos em um delta escalar de zoom antes do navegador receber qualquer coisa. - Rolagem em ambos os dispositivos — converge no mesmo evento
wheel, tornando a rolagem o gesto mais portátil para lidar:addEventListener("wheel", handler)captura rolagem com dois dedos no trackpad e delegação de overscroll na tela sensível ao toque igualmente.
Essa divisão arquitetural é proposital. O sistema operacional processa os contatos brutos de múltiplos dedos do touchpad e entrega eventos finalizados e semanticamente rotulados para o navegador. O navegador então encaminha esses eventos para as páginas. Uma tela sensível ao toque, por outro lado, passa dados brutos de contato para o navegador, por isso o código web pode implementar lógica customizada de pinça em uma tela sensível ao toque, mas não pode fazer o mesmo em um trackpad de desktop sem sair da plataforma web padrão.
Como o testador reflete esse design
O módulo GestureDetector do testador usa essa divisão deliberadamente. Tap, double-tap, long-press e swipe são detectados via ouvintes PointerEvent — os mesmos eventos que um trackpad dispara como eventos pointerType: "mouse". Rolagem é detectada via ouvintes de evento wheel. Pinça, no entanto, é detectada via TouchEvent (touchstart, touchmove) — verificando especificamente dois contatos simultâneos e medindo a mudança na distância entre eles. Se a distância mudar mais de 30 pixels, uma pinça é acionada. Em um trackpad de desktop esse caminho nunca dispara porque nenhum TouchEvent chega; a pinça no trackpad chega ao navegador apenas como um evento ctrl+wheel, que o painel de gestos conta como rolagem em vez de pinça. Em uma tela sensível ao toque, o caminho TouchEvent dispara corretamente e o contador de pinça incrementa.
Uma limitação prática que vale notar: nenhuma das APIs expõe dados brutos de contato dos dedos de um trackpad de desktop para uma página web. Uma ferramenta de teste pode observar que um evento ctrl+wheel foi disparado, mas não pode informar quantos dedos o produziram ou quais eram as posições brutas do contato — essa informação é consumida pelo sistema operacional antes de chegar ao navegador.
Teste você mesmo: use a ferramenta acima em um trackpad de laptop e tente um gesto de pinça com dois dedos. Se o painel de Detecção de Gestos não mostrar o contador de pinça aumentando, você está em um trackpad de desktop onde a pinça chega comoctrl+wheelem vez deTouchEvent. Mude para um dispositivo com tela sensível ao toque e repita o gesto — o contador de pinça deve aumentar, confirmando que o caminho de pinça com dois dedosTouchEventestá ativo.