Używaj interfejsu Generic Sensor API, aby uzyskać dostęp do czujników na urządzeniu, takich jak akcelerometry, żyroskopy i magnetometry.
Obecnie dane z czujników są wykorzystywane w wielu aplikacjach działających na konkretnych platformach, na przykład wciągające gry, śledzenie aktywności fizycznej oraz rzeczywistość rozszerzoną lub wirtualną. Czy nie byłoby wspaniale przejść przez most między aplikacjami zależnymi od platformy a aplikacjami internetowymi? Wpisz wartość Ogólny Sensor API do użytku w internecie.
Czym jest interfejs Generative Sensor API?
Generic Sensor API to zestaw interfejsów, które udostępniają urządzenia czujnikowe platformie internetowej. Interfejs API składa się z elementów
Interfejs Sensor
i zestaw konkretnych
i klasy czujników. Dzięki interfejsowi podstawowemu upraszcza się proces implementacji i specyfikacji konkretnych klas czujników. Spójrz na przykład na
Gyroscope
. Jest bardzo malutki!
główna funkcjonalność jest określana przez interfejs podstawowy, a Gyroscope
rozszerza ją o trzy
atrybutów reprezentujących prędkość kątową.
Niektóre klasy czujników łączą się z rzeczywistymi czujnikami sprzętowymi, takimi jak akcelerometr lub
lekcji żyroskopu. Są to tak zwane czujniki niskiego poziomu. Inne czujniki, zwane czujnikami fuzji, łączą dane z kilku czujników niskiego poziomu, aby udostępniać informacje, które skrypt musiałby inaczej obliczyć. Na przykład parametr
Czujnik AbsoluteOrientation
zapewnia gotową do użycia macierz obrotu w układzie 4:4, opartą na danych uzyskanych
akcelerometr, żyroskop i magnetometr.
Możesz myśleć, że platforma internetowa już udostępnia dane z czujników. I masz absolutną rację! Na przykład zdarzenia DeviceMotion
i DeviceOrientation
udostępniają dane z czujnika ruchu. Dlaczego więc potrzebujemy nowego interfejsu API?
W porównaniu z dotychczasowymi interfejsami interfejs Generic Sensor API zapewnia wiele korzyści:
- Interfejs General Sensor API to platforma czujników, którą można łatwo rozszerzyć za pomocą nowych klas czujników i każda z nich zachowa ogólny interfejs. Kod klienta napisany dla jednego typu czujnika można wykorzystać do innego z niewielkimi modyfikacjami.
- Możesz skonfigurować czujnik. Możesz na przykład ustawić częstotliwość próbkowania odpowiednią do potrzeb aplikacji.
- Możesz sprawdzić, czy na platformie jest dostępny czujnik.
- Odczyty czujników mają znaczniki czasu o wysokiej dokładności, co umożliwia lepszą synchronizację z innymi działaniami w aplikacji.
- Modele danych czujników i układy współrzędnych są jasno zdefiniowane, dzięki czemu dostawcy przeglądarek mogą wdrażania rozwiązań interoperacyjnych.
- Interfejsy oparte na czujnikach ogólnych nie są powiązane z DOM (co oznacza, że nie są
navigator
ani obiektówwindow
), co otwiera możliwości korzystania z interfejsu API w usłudze w przyszłości. lub implementować w środowiskach wykonawczych JavaScript bez interfejsu graficznego, takich jak urządzenia. - Aspekty bezpieczeństwa i prywatności mają najwyższy priorytet. API i zapewniają znacznie lepsze zabezpieczenia w porównaniu ze starszymi interfejsami API czujników. Istnieje integracja z interfejsem Permissions API.
- Automatyczna synchronizacja z koordynatami ekranu jest dostępna w przypadku usług
Accelerometer
,Gyroscope
,LinearAccelerationSensor
,AbsoluteOrientationSensor
,RelativeOrientationSensor
iMagnetometer
.
Dostępne ogólne interfejsy API czujników
W momencie pisania tego artykułu dostępnych jest kilka czujników, z którymi możesz eksperymentować.
Czujniki ruchu:
Accelerometer
Gyroscope
LinearAccelerationSensor
AbsoluteOrientationSensor
RelativeOrientationSensor
GravitySensor
Czujniki środowiskowe:
AmbientLightSensor
(za flagą#enable-generic-sensor-extra-classes
w Chromium).Magnetometer
(za flagą#enable-generic-sensor-extra-classes
w Chromium).
Wykrywanie cech
Wykrywanie funkcji interfejsów API sprzętowych jest trudne, ponieważ trzeba wykryć, czy przeglądarka obsługuje dany interfejs, oraz czy urządzenie ma odpowiedni czujnik. Konto rozliczeniowe
czy przeglądarka obsługuje odpowiedni interfejs. (Zastąp Accelerometer
dowolnym z tych elementów
innych interfejsów wymienionych powyżej).
if ('Accelerometer' in window) {
// The `Accelerometer` interface is supported by the browser.
// Does the device have an accelerometer, though?
}
Aby uzyskać wiarygodny wynik wykrywania funkcji, musisz też spróbować połączyć się z czujnikiem. Ten przykład pokazuje, jak to zrobić.
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;
}
}
Watolina
W przypadku przeglądarek, które nie obsługują interfejsu Generic Sensor API, dostępna jest funkcja polyfill. Dzięki polyfillowi możesz wczytywać tylko implementacje odpowiednich czujników.
// 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 });
Co to za wszystkie te czujniki? Jak mogę ich używać?
Czujniki to zagadnienie, o którym warto wspomnieć. Jeśli znasz się na czujnikach, możesz przejść od razu do sekcji poświęconej programowaniu praktycznemu. Przyjrzyjmy się teraz każdemu z nich z czujnika.
Akcelerometr i czujnik przyspieszenia liniowego
Czujnik Accelerometer
mierzy przyspieszenie urządzenia, na którym jest zainstalowany, na trzech osiach (X, Y i Z). Ten czujnik jest
czujnika bezwładnego, co oznacza, że gdy urządzenie znajduje się w liniowym swobodnym spadaniu, całkowita liczba
przyspieszenie wyniesie 0 m/s2, a gdy urządzenie leży płasko na stole, przyspieszenie
w kierunku do góry (oś Z) będzie równa grawitacji Ziemi, tj. g ≈ +9,8 m/s2
Wskazuje on siłę, na jaką stół pcha urządzenie w górę. Jeśli umieścisz urządzenie w
do prawej, przyspieszenie na osi X będzie dodatnie lub ujemne, jeśli przyspieszenie
w prawo, w lewo.
Akcelerometr może służyć np. do liczenia kroków, wykrywania ruchu lub prostych urządzeń. orientacji ekranu. Pomiary z akcelerometru są często łączone z danymi z innych źródeł, czujniki Fusion, takie jak czujniki orientacji.
LinearAccelerationSensor
zmierzyć przyspieszenie zastosowane do urządzenia, na którym znajduje się czujnik, z wyłączeniem wpływu grawitacji. Gdy urządzenie jest nieruchome, np. leży na stole, czujnik mierzy przyspieszenie ≈ 0 m/s2 na trzech osiach.
Czujnik grawitacji
Użytkownicy mogą już ręcznie uzyskiwać odczyty zbliżone do odczytów z czujnika grawitacyjnego, ręcznie sprawdzając odczyty Accelerometer
i LinearAccelerometer
, ale może to być uciążliwe i zależy od dokładności wartości dostarczanych przez te czujniki. Takie platformy jak Android
udostępniają odczyty grawitacji w ramach systemu operacyjnego, co powinno być tańsze pod względem
pozwala na generowanie dokładniejszych wartości w zależności od sprzętu użytkownika i łatwiejsze korzystanie
pod kątem ergonomii interfejsów API.
GravitySensor
zwraca efekt.
przyspieszenia wzdłuż osi X, Y i Z urządzenia z powodu grawitacji.
Żyroskop
Czujnik Gyroscope
mierzy
prędkość kątowa w radianach na sekundę wokół lokalnej osi X, Y i Z urządzenia. Większość konsumentów
urządzenia są wyposażone w mechanizm (MEMS)
żyroskopy, które są czujnikami bezwładnymi mierzącymi prędkość obrotu na podstawie
siły wewnętrznej Coriolisa. Żyroskopy MEMS są podatne na dryf spowodowany przez czułość na przyciąganie ziemskie, która deformuje wewnętrzny system mechaniczny czujnika. żyroskopy oscylują z relatywnie wysokimi częstotliwościami, np. 10 s kHz oraz
dlatego może zużywać więcej energii w porównaniu z innymi czujnikami.
Czujniki orientacji
AbsoluteOrientationSensor
to czujnik fuzji, który mierzy obrót urządzenia w odniesieniu do układu współrzędnych Ziemi,
podczas gdy
RelativeOrientationSensor
dostarcza dane przedstawiające obrót urządzenia z czujnikami ruchu w odniesieniu do miejsca nieruchomego
wsadowy układ współrzędnych.
Wszystkie nowoczesne platformy JavaScript 3D obsługują kwaterniony i macierze obrotu do reprezentowania obrotu. Jeśli jednak używasz bezpośrednio WebGL, obiekt OrientationSensor
ma zarówno właściwość quaternion
, jak i metodę populateMatrix()
.
Oto kilka fragmentów kodu:
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();
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);
Czujniki orientacji umożliwiają różne zastosowania, takie jak wciągające gry, rzeczywistość rozszerzona i wirtualna.
Więcej informacji o czujnikach ruchu, zaawansowanych zastosowaniach i wymaganiach znajdziesz w artykule Opis czujników ruchu.
Synchronizacja z koordynatami ekranu
Domyślnie odczyty czujników przestrzennych są przetwarzane w lokalnym układzie współrzędnych powiązanym z urządzeniem i nie uwzględniającym orientacji ekranu.
Jednak w wielu przypadkach użycia, takich jak gry czy rzeczywistość rozszerzona i wirtualna, odczyty z czujników muszą być w układzie współrzędnych, który jest powiązany z orientacją ekranu.
Wcześniej mapowanie odczytów z czujników do współrzędnych ekranu trzeba było wdrażać w JavaScripcie. Takie podejście jest nieefektywne i znacznie zwiększa złożoność kodu aplikacji internetowej. Aplikacja internetowa musi obserwować zmiany orientacji ekranu i przekształcać współrzędne odczytów czujnika, co nie jest proste w przypadku kątów Eulera ani kwaternionów.
Interfejs Generic Sensor API to znacznie prostsze i bardziej niezawodne rozwiązanie. Lokalny system współrzędnych można skonfigurować dla wszystkich zdefiniowanych klas czujników przestrzennych: Accelerometer
, Gyroscope
, LinearAccelerationSensor
, AbsoluteOrientationSensor
, RelativeOrientationSensor
i Magnetometer
. Przekazując opcję referenceFrame
do konstruktora obiektów czujnika, użytkownik
określa, czy zwrócone odczyty zostaną rozwiązane w
device lub
Współrzędne ekranu.
// 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' });
Kodujmy!
Interfejs Generative Sensor API jest bardzo prosty i łatwy w użyciu. Interfejs czujnika
start()
i
Metody stop()
do kontrolowania stanu czujnika oraz kilku
moduły obsługi zdarzeń do otrzymywania powiadomień o aktywowaniu czujników, błędach i nowo dostępnych
odczyty. Klasy konkretnych czujników zwykle dodają do klasy podstawowej określone atrybuty odczytu.
Środowisko programistyczne
Podczas programowania będzie można używać czujników w programie localhost
. Jeśli tworzysz aplikację na urządzenia mobilne, skonfiguruj przekierowanie portów na serwerze lokalnym.
Gdy kod będzie gotowy, wdróż go na serwerze, który obsługuje HTTPS. Strony GitHub są wyświetlane przez HTTPS, dzięki czemu warto je udostępniać w Twoich wersjach demonstracyjnych.
Obracanie modelu 3D
W tym prostym przykładzie używamy danych z czujnika orientacji bezwzględnej, aby zmodyfikować obrót
kwartion modelu 3D. Obiekt model
jest instancją klasy Object3D
z biblioteki three.js, która ma właściwość quaternion
.
ten fragment kodu z
telefon w orientacji poziomej
ilustruje sposób użycia czujnika orientacji bezwzględnej do obracania modelu 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();
}
Orientacja urządzenia będzie odzwierciedlona w obrocie 3D model
w scenie WebGL.
Punchmeter
Następujący fragment kodu jest wyodrębniony z pliku prezentacja Punchmeter, przedstawia sposób użycia czujnika przyspieszenia liniowego do obliczania maksymalnej prędkości przy założeniu, że początkowo leży nieruchomo.
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;
};
Bieżąca prędkość jest obliczana jako przybliżenie całki funkcji przyspieszenia.
Debugowanie i zastępowanie czujników w Narzędziach deweloperskich w Chrome
W niektórych przypadkach do korzystania z interfejsu General Sensor API nie potrzebujesz fizycznego urządzenia. Narzędzia deweloperskie w Chrome zapewniają świetne wsparcie w symulowaniu orientacji urządzenia.
Prywatność i bezpieczeństwo
Odczyty z czujników to dane wrażliwe, które mogą być celem różnych ataków ze złośliwych stron internetowych. Implementacje interfejsów API czujników ogólnych narzucają kilka ograniczeń, aby ograniczyć możliwe zagrożenia dla bezpieczeństwa i prywatności. Deweloperzy, którzy chcą korzystać z interfejsu API, muszą wziąć pod uwagę te ograniczenia. Oto ich krótki opis.
Tylko HTTPS
Interfejs Generic Sensor API jest potężną funkcją, dlatego przeglądarka zezwala na jego użycie tylko w bezpiecznych kontekstach. W oznacza to, że aby korzystać z interfejsu Generative Sensor API, musisz uzyskiwać dostęp do strony przez HTTPS. W trakcie programowania możesz to zrobić przez http://localhost, ale w wersji produkcyjnej niezbędny jest protokół HTTPS na Twoim serwerze. Sprawdzone metody znajdziesz w kolekcji Bezpieczeństwo i ochrona. i wytycznych.
Integracja z zasadami dotyczącymi uprawnień
Integracja z zasadami dotyczącymi uprawnień w sekcji Ogólna Interfejs Sensor API kontroluje dostęp do danych z czujników klatki.
Domyślnie obiekty Sensor
mogą być tworzone tylko w ramach głównego elementu iframe lub podelementów iframe tego samego pochodzenia, co uniemożliwia nieautoryzowane odczytywanie danych z czujników przez iframe z innego pochodzenia. To domyślne zachowanie można zmienić, wyraźnie włączając lub wyłączając odpowiednie funkcje kontrolowane przez zasady.
Poniżej znajduje się fragment kodu, który pokazuje, jak przyznać dostęp do danych akcelerometru do ramki iframe w innej domenie. Oznacza to, że teraz można tworzyć w niej obiekty Accelerometer
lub LinearAccelerationSensor
.
<iframe src="https://third-party.com" allow="accelerometer" />
Dostarczanie odczytów z czujników może zostać zawieszone.
Wyniki pomiarów czujników są dostępne tylko dla widocznej strony internetowej, czyli wtedy, gdy użytkownik faktycznie z nią współpracuje. Ponadto dane z czujnika nie będą przekazywane do ramki nadrzędnej, jeśli użytkownik i zaznacz zmiany na ramce podrzędnej z innej domeny. Zapobiega to wywnioskowaniu danych wejściowych użytkownika przez ramkę nadrzędną.
Co dalej?
W najbliższej przyszłości zostanie zaimplementowany zestaw już określonych klas czujników, takich jak czujnik jasności otoczenia czy czujnik zbliżeniowy. Jednak dzięki dużej możliwości rozszerzalności Generic Sensor framework możemy spodziewać się pojawienia jeszcze większej liczby nowych klas reprezentujących różne typy czujników.
Kolejnym ważnym obszarem do dalszego rozwijania jest ulepszenie samego interfejsu Generic Sensor API. Specyfikacja Generic Sensor jest obecnie w fazie rekomendacji, co oznacza, że wciąż jest czas na wprowadzenie poprawek i nowych funkcji potrzebnych deweloperom.
Możesz pomóc.
Specyfikacja czujnika Rekomendacja kandydatów dojrzałości cyfrowej, dlatego opinie programistów internetu i przeglądarek są dla nas bardzo ważne. Daj nam znać, jakie funkcje warto dodać lub co można zmienić w obecnym interfejsie API.
Zgłaszaj problemy ze specyfikacją oraz błędy związane z implementacją w Chrome.
Zasoby
- Projekty demonstracyjne: https://intel.github.io/generic-sensor-demos/
- Ogólna specyfikacja interfejsu Sensor API: https://w3c.github.io/sensors/
- Problemy ze specyfikacją: https://github.com/w3c/sensors/issues
- Lista adresów e-mail grupy roboczej W3C: public-device-apis@w3.org
- Stan funkcji Chrome: https://www.chromestatus.com/feature/5698781827825664
- Błędy implementacji: http://crbug.com?q=component:Blink>Sensor
Podziękowania
Ten artykuł został zrecenzowany przez Joe Medley i Kayce Basques Baner powitalny autorstwa Misko z Wikimedia Commons.