Use a API Generic Sensor para acessar sensores no dispositivo, como acelerômetros, giroscópios e magnetômetros.
Atualmente, os dados dos sensores são usados em muitos aplicativos específicos da plataforma para permitir casos de uso como jogos imersivos, monitoramento de condicionamento físico e realidade aumentada ou virtual. Não seria legal preencher a lacuna entre os aplicativos da Web e os específicos da plataforma? Acesse a API Generic Sensor para a Web.
O que é a API Generic Sensor?
A API Generic Sensor é um conjunto de interfaces que expõe
dispositivos de sensor à plataforma da Web. A API consiste na interface
Sensor
básica e em um conjunto de classes de sensor
concretas criadas na parte de cima. Ter uma interface base simplifica o processo de implementação e especificação
das classes de sensor concretas. Por exemplo, observe a classe
Gyroscope
. É bem minúsculo! A
funcionalidade principal é especificada pela interface base, e o Gyroscope
apenas a estende com três
atributos que representam a velocidade angular.
Algumas classes de sensor interagem com sensores de hardware reais, como as classes de acelerômetro ou
giroscópio. Eles são chamados de sensores de baixo nível. Outros sensores, chamados de
sensores de fusão, mesclam dados de vários sensores de baixo nível
para expor informações que um script precisaria calcular. Por exemplo, o
sensor AbsoluteOrientation
fornece uma matriz de rotação de quatro por quatro pronta para uso com base nos dados coletados do
acelerômetro, do giroscópio e do magnetômetro.
Talvez você ache que a plataforma da Web já fornece dados dos sensores e acertou! Por
exemplo, os eventos DeviceMotion
e
DeviceOrientation
expõem dados do sensor de movimento. Por que precisamos de uma nova API?
Em comparação com as interfaces existentes, a API Generic Sensor oferece muitas vantagens:
- A API Generic Sensor é um framework que pode ser facilmente estendido com novas classes de sensor. Cada uma delas vai manter a interface genérica. O código do cliente escrito para um tipo de sensor pode ser reutilizado em outro com pouquíssimas modificações.
- Você pode configurar o sensor. Por exemplo, é possível definir a frequência de amostragem adequada para as necessidades do seu aplicativo.
- Você pode detectar se um sensor está disponível na plataforma.
- As leituras do sensor têm carimbos de data/hora de alta precisão, o que permite uma melhor sincronização com outras atividades no app.
- Os modelos de dados de sensores e sistemas de coordenadas são claramente definidos, permitindo que os fornecedores de navegadores implementem soluções interoperáveis.
- As interfaces baseadas em sensor genérico não são vinculadas ao DOM, ou seja, elas não são objetos
navigator
nemwindow
. Isso abre oportunidades futuras para usar a API em service workers ou implementá-la em ambientes de execução headless do JavaScript, como dispositivos incorporados. - Os aspectos de segurança e privacidade são a principal prioridade da API Generic Sensor e oferecem uma segurança muito melhor em comparação com APIs de sensor mais antigas. Há uma integração com a API Permissions.
- A sincronização automática com coordenadas da tela está
disponível para
Accelerometer
,Gyroscope
,LinearAccelerationSensor
,AbsoluteOrientationSensor
,RelativeOrientationSensor
eMagnetometer
.
APIs de sensor genérico disponíveis
Atualmente, existem vários sensores que você pode usar.
Sensores de movimento:
Accelerometer
Gyroscope
LinearAccelerationSensor
AbsoluteOrientationSensor
RelativeOrientationSensor
GravitySensor
Sensores ambientais:
AmbientLightSensor
(atrás da sinalização#enable-generic-sensor-extra-classes
no Chromium)Magnetometer
(atrás da sinalização#enable-generic-sensor-extra-classes
no Chromium)
Detecção de recursos
A detecção de recursos das APIs de hardware é complicada, porque é preciso detectar se o navegador
oferece suporte à interface em questão e se o dispositivo tem o sensor correspondente. Verificar se o navegador oferece suporte a uma interface é simples. Substitua Accelerometer
por qualquer uma das
outras interfaces mencionadas acima.
if ('Accelerometer' in window) {
// The `Accelerometer` interface is supported by the browser.
// Does the device have an accelerometer, though?
}
Para conseguir um resultado significativo com a detecção de recursos, você também precisa tentar se conectar ao sensor. Este exemplo mostra como fazer isso.
let accelerometer = null;
try {
accelerometer = new Accelerometer({ frequency: 10 });
accelerometer.onerror = (event) => {
// Handle runtime errors.
if (event.error.name === 'NotAllowedError') {
console.log('Permission to access sensor was denied.');
} else if (event.error.name === 'NotReadableError') {
console.log('Cannot connect to the sensor.');
}
};
accelerometer.onreading = (e) => {
console.log(e);
};
accelerometer.start();
} catch (error) {
// Handle construction errors.
if (error.name === 'SecurityError') {
console.log('Sensor construction was blocked by the Permissions Policy.');
} else if (error.name === 'ReferenceError') {
console.log('Sensor is not supported by the User Agent.');
} else {
throw error;
}
}
Plástico poligonal
Para navegadores que não são compatíveis com a API Generic Sensor, um polyfill está disponível. O polyfill permite carregar apenas as implementações dos sensores relevantes.
// Import the objects you need.
import { Gyroscope, AbsoluteOrientationSensor } from './src/motion-sensors.js';
// And they're ready for use!
const gyroscope = new Gyroscope({ frequency: 15 });
const orientation = new AbsoluteOrientationSensor({ frequency: 60 });
O que são todos esses sensores? Como posso usá-los?
Sensores é uma área que pode precisar de uma breve introdução. Se você já conhecer os sensores, vá direto para a seção de programação prática. Caso contrário, vamos analisar cada sensor compatível em detalhes.
Acelerômetro e sensor de aceleração linear
O sensor Accelerometer
mede a aceleração de um dispositivo que hospeda o sensor em três eixos (X, Y e Z). Esse é um
sensor inercial. Isso significa que, quando o dispositivo está em queda livre linear, a aceleração total medida
é de 0 m/s2, e quando um dispositivo está deitado sobre uma mesa, a aceleração
para cima (eixo Z) é igual à da gravidade da Terra, ou seja, g ≤ +9,8 m/s de aceleração2 quando o dispositivo está medindo a
tabela.2 Se você empurrar o dispositivo para a
direita, a aceleração no eixo X será positiva ou negativa, se o dispositivo for acelerado da
direita para a esquerda.
Os acelerômetros podem ser usados para, por exemplo, contagem de passos, detecção de movimento ou orientação simples do dispositivo. Muitas vezes, as medições do acelerômetro são combinadas com dados de outras fontes para criar sensores de fusão, como sensores de orientação.
O
LinearAccelerationSensor
mede a aceleração aplicada ao dispositivo que hospeda o sensor, excluindo a contribuição
da gravidade. Quando um dispositivo está em repouso, por exemplo, deitado sobre a mesa, o sensor mediria
✕ 0 m/s2 a aceleração em três eixos.
Sensor de gravidade
Os usuários já podem derivar manualmente leituras próximas às de um sensor de gravidade
inspecionando manualmente as leituras Accelerometer
e LinearAccelerometer
, mas isso pode ser complicado
e depender da precisão dos valores fornecidos por esses sensores. Plataformas como o Android podem
fornecer leituras de gravidade como parte do sistema operacional, que é mais barato em termos de
computação, fornece valores mais precisos, dependendo do hardware do usuário, e é mais fácil de usar em
termos de ergonomia da API. O
GravitySensor
retorna o efeito
de aceleração ao longo dos eixos X, Y e Z do dispositivo devido à gravidade.
Giroscópio
O sensor Gyroscope
mede
a velocidade angular em radianos por segundo em torno dos eixos locais X, Y e Z do dispositivo. A maioria dos dispositivos
consumidores tem giroscópios mecânicos (MEMS,
link em inglês), que são sensores de inércia que medem a taxa de rotação com base na
força inercial de Coriolis (link em inglês). Os giroscópios de MEMS são propensos
a desvios causados pela sensibilidade gravitacional do sensor, que deforma o sistema mecânico interno
do sensor. Os giroscópios oscilam em frequências altas relativas, por exemplo, 10s de kHz e, portanto, podem consumir mais energia em comparação com outros sensores.
Sensores de orientação
O
AbsoluteOrientationSensor
é um sensor de fusão que mede a rotação de um dispositivo em relação ao sistema de coordenadas da Terra,
enquanto o
RelativeOrientationSensor
fornece dados que representam a rotação de um dispositivo que hospeda sensores de movimento em relação a um sistema de coordenadas
de referência estacionária.
Todos os frameworks modernos de JavaScript 3D oferecem suporte a quatérios
e matrizes de rotação para representar a rotação.
No entanto, se você usar o WebGL diretamente, o OrientationSensor
terá convenientemente uma
propriedade quaternion
e um
populateMatrix()
método (links em inglês).
Confira alguns snippets:
let torusGeometry = new THREE.TorusGeometry(7, 1.6, 4, 3, 6.3);
let material = new THREE.MeshBasicMaterial({ color: 0x0071c5 });
let torus = new THREE.Mesh(torusGeometry, material);
scene.add(torus);
// Update mesh rotation using quaternion.
const sensorAbs = new AbsoluteOrientationSensor();
sensorAbs.onreading = () => torus.quaternion.fromArray(sensorAbs.quaternion);
sensorAbs.start();
// Update mesh rotation using rotation matrix.
const sensorRel = new RelativeOrientationSensor();
let rotationMatrix = new Float32Array(16);
sensor_rel.onreading = () => {
sensorRel.populateMatrix(rotationMatrix);
torus.matrix.fromArray(rotationMatrix);
};
sensorRel.start();
BABBYLON (em inglês)
const mesh = new BABYLON.Mesh.CreateCylinder('mesh', 0.9, 0.3, 0.6, 9, 1, scene);
const sensorRel = new RelativeOrientationSensor({ frequency: 30 });
sensorRel.onreading = () => mesh.rotationQuaternion.FromArray(sensorRel.quaternion);
sensorRel.start();
// Initialize sensor and update model matrix when new reading is available.
let modMatrix = new Float32Array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
const sensorAbs = new AbsoluteOrientationSensor({ frequency: 60 });
sensorAbs.onreading = () => sensorAbs.populateMatrix(modMatrix);
sensorAbs.start();
// Somewhere in rendering code, update vertex shader attribute for the model
gl.uniformMatrix4fv(modMatrixAttr, false, modMatrix);
Os sensores de orientação permitem vários casos de uso, como jogos imersivos, realidade aumentada e virtual.
Para mais informações sobre sensores de movimento, casos de uso avançados e requisitos, confira o documento de explicação sobre sensores de movimento.
Sincronização com coordenadas da tela
Por padrão, as leituras de sensores espaciais são resolvidas em um sistema de coordenadas local vinculado ao dispositivo, que não considera a orientação da tela.
![Sistema de coordenadas do dispositivo](https://developer.chrome.google.cn/static/docs/capabilities/web-apis/generic-sensor/image/device-coordinate-system-c67b130c9d772.png?authuser=5&hl=pt)
No entanto, muitos casos de uso, como jogos ou realidade aumentada e virtual, exigem que as leituras do sensor sejam resolvidas em um sistema de coordenadas vinculado à orientação da tela.
![Sistema de coordenadas da tela](https://developer.chrome.google.cn/static/docs/capabilities/web-apis/generic-sensor/image/screen-coordinate-system-e3fae643f502a.png?authuser=5&hl=pt)
Anteriormente, o remapeamento de leituras de sensores em coordenadas da tela precisava ser implementado em JavaScript. Essa abordagem é ineficiente e aumenta significativamente a complexidade do código do aplicativo da Web. Ele precisa observar as mudanças na orientação da tela e realizar transformações de coordenadas para leituras do sensor, o que não é algo trivial de se fazer para ângulos de Euler ou quaternões.
A API Generic Sensor oferece uma solução muito mais simples e confiável. O sistema de coordenadas local é
configurável para todas as classes de sensores espaciais definidas: Accelerometer
, Gyroscope
,
LinearAccelerationSensor
, AbsoluteOrientationSensor
, RelativeOrientationSensor
e
Magnetometer
. Ao transmitir a opção referenceFrame
para o construtor do objeto do sensor, o usuário
define se as leituras retornadas serão resolvidas nas coordenadas do
dispositivo ou da
tela.
// Sensor readings are resolved in the Device coordinate system by default.
// Alternatively, could be RelativeOrientationSensor({referenceFrame: "device"}).
const sensorRelDevice = new RelativeOrientationSensor();
// Sensor readings are resolved in the Screen coordinate system. No manual remapping is required!
const sensorRelScreen = new RelativeOrientationSensor({ referenceFrame: 'screen' });
Vamos começar a programar.
A API Generic Sensor é muito simples e fácil de usar. A interface do sensor tem os métodos
start()
e
stop()
para controlar o estado do sensor e vários
manipuladores de eventos para receber notificações sobre ativação do sensor, erros e leituras
recém-disponíveis. As classes de sensor concretas geralmente adicionam os atributos de leitura específicos à classe
base.
Ambiente de desenvolvimento
Durante o desenvolvimento, você vai poder usar sensores com localhost
. Se você estiver desenvolvendo para
dispositivos móveis, configure o
encaminhamento de portas
para seu servidor local e pronto.
Quando o código estiver pronto, implante-o em um servidor compatível com HTTPS. As páginas do GitHub são veiculadas em HTTPS, o que a torna um ótimo lugar para compartilhar suas demonstrações.
Rotação do modelo 3D
Neste exemplo simples, usamos os dados de um sensor de orientação absoluta para modificar o quatérnio de
rotação de um modelo 3D. O model
é uma instância da classe Object3D
do three.js que tem uma propriedade
quaternion
. O
snippet de código a seguir da demonstração do
telefone de orientação
mostra como o sensor de orientação absoluta pode ser usado para girar um modelo 3D.
function initSensor() {
sensor = new AbsoluteOrientationSensor({ frequency: 60 });
sensor.onreading = () => model.quaternion.fromArray(sensor.quaternion);
sensor.onerror = (event) => {
if (event.error.name == 'NotReadableError') {
console.log('Sensor is not available.');
}
};
sensor.start();
}
A orientação do dispositivo será refletida na rotação 3D model
na cena WebGL.
![O sensor atualiza a orientação do modelo 3D](https://developer.chrome.google.cn/static/docs/capabilities/web-apis/generic-sensor/image/sensor-updates-3d-models-270d2e43cbcb1.png?authuser=5&hl=pt)
Perfurador
O snippet de código a seguir é extraído da demonstração do medidor de perfuração, ilustrando como o sensor de aceleração linear pode ser usado para calcular a velocidade máxima de um dispositivo, supondo que ele esteja inicialmente parado.
this.maxSpeed = 0;
this.vx = 0;
this.ax = 0;
this.t = 0;
/* … */
this.accel.onreading = () => {
let dt = (this.accel.timestamp - this.t) * 0.001; // In seconds.
this.vx += ((this.accel.x + this.ax) / 2) * dt;
let speed = Math.abs(this.vx);
if (this.maxSpeed < speed) {
this.maxSpeed = speed;
}
this.t = this.accel.timestamp;
this.ax = this.accel.x;
};
A velocidade atual é calculada como uma aproximação à integral da função de aceleração.
![Aplicativo da Web de demonstração para medição da velocidade da perfuração](https://developer.chrome.google.cn/static/docs/capabilities/web-apis/generic-sensor/image/demo-web-application-pun-b24949530ffe1.png?authuser=5&hl=pt)
Depuração e substituição de sensores com o Chrome DevTools
Em alguns casos, você não precisa de um dispositivo físico para usar a API Generic Sensor. O Chrome DevTools tem um ótimo suporte para simular a orientação do dispositivo.
![Chrome DevTools usado para substituir os dados de orientação personalizada de um smartphone virtual](https://developer.chrome.google.cn/static/docs/capabilities/web-apis/generic-sensor/image/chrome-devtools-used-ove-80ebd2eaae558.png?authuser=5&hl=pt)
Privacidade e segurança
As leituras dos sensores são dados confidenciais que podem estar sujeitos a vários ataques de páginas da Web maliciosas. As implementações das APIs Generic Sensor aplicam algumas limitações para reduzir os possíveis riscos de segurança e privacidade. Essas limitações precisam ser consideradas pelos desenvolvedores que pretendem usar a API. Então, vamos listá-las brevemente.
Somente HTTPS
Como a API Generic Sensor é um recurso avançado, o navegador só a permite em contextos seguros. Na prática, isso significa que, para usar a API Generic Sensor, será necessário acessar sua página por HTTPS. Durante o desenvolvimento, é possível fazer isso por meio de http://localhost. No entanto, para a produção, será necessário ter HTTPS no servidor. Consulte a coleção Seguro e protegido para ver práticas recomendadas e diretrizes.
Integração da política de permissões
A integração da política de permissões na API Generic Sensor controla o acesso aos dados dos sensores de um frame.
Por padrão, os objetos Sensor
só podem ser criados em um frame principal ou subframes de mesma origem,
evitando que iframes de origem cruzada leiam dados do sensor não autorizados. Esse comportamento padrão
pode ser modificado ativando ou desativando explicitamente os recursos controlados por política
correspondentes.
O snippet abaixo ilustra a concessão de acesso aos dados do acelerômetro para um iframe de origem cruzada, o que significa que agora objetos Accelerometer
ou LinearAccelerationSensor
podem ser criados nele.
<iframe src="https://third-party.com" allow="accelerometer" />
A entrega de leituras do sensor pode ser suspensa
As leituras do sensor só podem ser acessadas por uma página da Web visível, ou seja, quando o usuário estiver realmente interagindo com ela. Além disso, os dados do sensor não vão ser fornecidos ao frame pai se o foco do usuário mudar para um subframe de origem cruzada. Isso evita que o frame pai deduza a entrada do usuário.
Qual é a próxima etapa?
Há um conjunto de classes de sensores já especificadas a serem implementadas em breve, como o Sensor de luz ambiente ou Sensor de proximidade. No entanto, graças à grande extensibilidade do framework do sensor genérico, podemos antecipar o surgimento de ainda mais classes novas que representam vários tipos de sensor.
Outra área importante para trabalhos futuros é melhorar a própria API Generic Sensor. A especificação Generic Sensor atualmente é uma recomendação candidata, o que significa que ainda há tempo para fazer correções e oferecer novas funcionalidades que os desenvolvedores precisam.
Você pode ajudar!
As especificações do sensor alcançaram o nível de maturidade recomendação candidata (link em inglês). Por isso, o feedback de desenvolvedores da Web e de navegadores é muito importante. Informe quais recursos seriam incríveis para adicionar ou se você gostaria de modificar algo na API atual.
Fique à vontade para registrar problemas de especificação e bugs relacionados à implementação do Chrome.
Recursos
- Projetos de demonstração: https://intel.github.io/generic-sensor-demos/ (link em inglês)
- Especificação genérica da API Sensor: https://w3c.github.io/sensors/ (link em inglês)
- Problemas de especificação: https://github.com/w3c/sensors/issues (link em inglês)
- Lista de e-mails do grupo de trabalho W3C: public-device-apis@w3.org
- Status do recurso do Chrome: https://www.chromestatus.com/feature/5698781827825664
- Bugs de implementação: http://crbug.com?q=component:Blink>Sensor
Agradecimentos
Este artigo foi revisado por Joe Medley e Kayce Basques. Imagem principal de Misko via Wikimedia Commons.