Como acessar os dados do acelerômetro / giroscópio a partir do Javascript?

139

Recentemente, encontrei alguns sites que parecem acessar o acelerômetro ou o giroscópio no meu laptop, detectando alterações na orientação ou no movimento.

Como isso é feito? Devo me inscrever em algum tipo de evento no windowobjeto?

Em quais dispositivos (laptops, telefones celulares, tablets) isso funciona?


NB : Eu já sei (em parte) a resposta a esta pergunta e vou publicá-la imediatamente. A razão pela qual estou postando a pergunta aqui é para que todos saibam que os dados do acelerômetro estão disponíveis em Javascript (em determinados dispositivos) e para desafiar a comunidade a publicar novas descobertas sobre o assunto. Atualmente, parece não haver quase nenhuma documentação desses recursos.

Jørn Schou-Rode
fonte
Grande esforço, muito obrigado. Você acha que, três anos depois, a resposta precisa de atualizações?
Bartek Banachewicz
@BartekBanachewicz Obrigado por me chamar neste. Transferirei a resposta para o "wiki da comunidade", esperando que alguém com mais conhecimento atualizado o atualize para refletir o estado da arte atual.
Jørn Schou-Rode
Não consegui descobrir se esta operação requer o consentimento do usuário. Não queria fazer uma nova pergunta, pois ela se encaixa perfeitamente na sua pergunta. Talvez possamos adicionar isso aqui? Alguém sabe se isso requer consentimento explícito? É esse o caso em todos os navegadores e sistemas operacionais móveis?
Silver

Respostas:

8

A maneira de fazer isso em 2019+ é usar a DeviceOrientationAPI . Isso funciona nos navegadores mais modernos em computadores e dispositivos móveis.

window.addEventListener("deviceorientation", handleOrientation, true);

Depois de registrar seu ouvinte de evento (nesse caso, uma função JavaScript chamada handleOrientation ()), sua função de ouvinte é periodicamente chamada com dados de orientação atualizados.

O evento de orientação contém quatro valores:

  • DeviceOrientationEvent.absolute
  • DeviceOrientationEvent.alpha
  • DeviceOrientationEvent.beta
  • DeviceOrientationEvent.gamma

A função do manipulador de eventos pode ser algo como isto:

function handleOrientation(event) {
  var absolute = event.absolute;
  var alpha    = event.alpha;
  var beta     = event.beta;
  var gamma    = event.gamma;
  // Do stuff with the new orientation data
}
str
fonte
179

Atualmente, existem três eventos distintos que podem ou não ser acionados quando os dispositivos clientes são movidos. Dois deles estão focados em orientação e o último em movimento :

  • ondeviceorientationé conhecido por funcionar na versão desktop do Chrome, e a maioria dos laptops da Apple parece ter o hardware necessário para que isso funcione. Também funciona no Mobile Safari no iPhone 4 com iOS 4.2. Na função de manipulador de eventos, você pode acessar alpha, beta, gammavalores sobre os dados do evento fornecidos como o único argumento para a função.

  • onmozorientationé suportado no Firefox 3.6 e mais recente. Novamente, isso é conhecido por funcionar na maioria dos laptops da Apple, mas também pode funcionar em máquinas Windows ou Linux com acelerômetro. Na função de manipulador de eventos, procure x, y, zcampos nos dados de eventos fornecido como primeiro argumento.

  • ondevicemotioné conhecido por funcionar no iPhone 3GS + 4 e iPad (ambos com iOS 4.2) e fornece dados relacionados à aceleração atual do dispositivo cliente. Os dados do evento passados para a função manipulador tem acceleratione accelerationIncludingGravityque ambos têm três campos para cada eixo: x, y,z

O site de exemplo "detecção de terremoto" usa uma série de ifinstruções para descobrir a qual evento anexar (em uma ordem um tanto priorizada) e passa os dados recebidos para uma tiltfunção comum :

if (window.DeviceOrientationEvent) {
    window.addEventListener("deviceorientation", function () {
        tilt([event.beta, event.gamma]);
    }, true);
} else if (window.DeviceMotionEvent) {
    window.addEventListener('devicemotion', function () {
        tilt([event.acceleration.x * 2, event.acceleration.y * 2]);
    }, true);
} else {
    window.addEventListener("MozOrientation", function () {
        tilt([orientation.x * 50, orientation.y * 50]);
    }, true);
}

Os fatores constantes 2 e 50 são usados ​​para "alinhar" as leituras dos dois últimos eventos com as do primeiro, mas essas representações não são de forma alguma precisas. Para este projeto simples de "brinquedo", ele funciona muito bem, mas se você precisar usar os dados para algo um pouco mais sério, precisará familiarizar-se com as unidades dos valores fornecidos nos diferentes eventos e tratá-los com respeito :)

Jørn Schou-Rode
fonte
9
às vezes uma resposta apenas diz a verdade!
Scott Evernden
1
Caso alguém se pergunte - o ondevicemotion funciona no Firefox 8.0, mas está dimensionado incorretamente (0-9), mas isso parece ter sido corrigido nas versões posteriores (10.0). Nenhum deles funciona no Opera Mobile e todos os padrão funcionam bem no navegador Nokia N9 padrão.
Nux
2
O evento MozOrientation foi removido como obsoleto no Firefox 6. Portanto, agora eles estão todos usando a API padronizada.
22812 Chris Morgan
Isso não parece funcionar no Firefox 30, como mostrado neste violino . :(
bwinton
sidenote: O Plax.js , usado nas páginas 404 e 500 do github, usa a orientação de dois dispositivos .
Yosh 29/09/14
21

Não é possível adicionar um comentário à excelente explicação no outro post, mas quero mencionar que uma excelente fonte de documentação pode ser encontrada aqui .

Basta registrar uma função de evento para o acelerômetro da seguinte forma:

if(window.DeviceMotionEvent){
  window.addEventListener("devicemotion", motion, false);
}else{
  console.log("DeviceMotionEvent is not supported");
}

com o manipulador:

function motion(event){
  console.log("Accelerometer: "
    + event.accelerationIncludingGravity.x + ", "
    + event.accelerationIncludingGravity.y + ", "
    + event.accelerationIncludingGravity.z
  );
}

E para o magnetômetro, um manipulador de eventos a seguir deve ser registrado:

if(window.DeviceOrientationEvent){
  window.addEventListener("deviceorientation", orientation, false);
}else{
  console.log("DeviceOrientationEvent is not supported");
}

com um manipulador:

function orientation(event){
  console.log("Magnetometer: "
    + event.alpha + ", "
    + event.beta + ", "
    + event.gamma
  );
}

Também existem campos especificados no evento de movimento para um giroscópio, mas isso não parece ser universalmente suportado (por exemplo, não funcionou em um Samsung Galaxy Note).

Existe um código de trabalho simples no GitHub

Estágio Infinito
fonte
1

Fallback útil aqui: https://developer.mozilla.org/en-US/docs/Web/Events/MozOrientation

function orientationhandler(evt){


  // For FF3.6+
  if (!evt.gamma && !evt.beta) {
    evt.gamma = -(evt.x * (180 / Math.PI));
    evt.beta = -(evt.y * (180 / Math.PI));
  }

  // use evt.gamma, evt.beta, and evt.alpha 
  // according to dev.w3.org/geo/api/spec-source-orientation


}

window.addEventListener('deviceorientation',  orientationhandler, false);
window.addEventListener('MozOrientation',     orientationhandler, false);
Luckylooke
fonte