Як використовувати датчики орієнтації в JavaScript за допомогою Gyro.js

Дізнайтеся з цієї статті, як ми просто використовували гіроскоп і акселерометр у браузері для заголовка сайту JS Республіка (звісно з мобільного) завдяки Gyro.js.

Маленьке нагадування

Телефон XNUMXd орієнтир
(джерело: http://www.alsacreations.com/tuto/lire/1501-api-device-orientation-motion-acceleration.html)
 
Перш ніж розпочати пояснення щодо їх використання в браузері, давайте швидко розглянемо, що це за датчики.
Ваш мобільний телефон використовує гіроскоп щоб знати його орієнтацію в просторі, цю орієнтацію виражають відповідно до альфа, бета і гамма, трьома кутами повороту в градусах навколо осей Z, X і Y.акселерометр використовується для вимірювання рухів вашого телефону в метрах/секунду² (вимірювання прискорення). У поєднанні ці два датчики можуть вимірювати прискорення обертання пристрою.
 
 

Випадок (не такий) простий

У HTML5 є два API для отримання вимірювань із цих датчиків: API орієнтації пристрою та API devicemotion , перший для відновлення орієнтації телефону (альфа, бета, гамма), а другий для відновлення прискорення рухів. Спочатку ми можемо отримати всю необхідну інформацію за допомогою кількох рядків JavaScript:

window.addEventListener('devicemotion', (eventData) => {
    console.log(`
        Angle Alpha : ${eventData.rotationRate.alpha}
        Angle Beta : ${eventData.rotationRate.beta}
        Angle Gamma : ${eventData.rotationRate.gamma}
        Accélération en X : ${eventData.accelerationIncludingGravity.x}
        Accélération en Y : ${eventData.accelerationIncludingGravity.Y}
        Accélération en Z : ${eventData.accelerationIncludingGravity.Z}
    `);
}, false);

З огляду на простоту API, не видається необхідним використовувати будь-яку бібліотеку! Ну, це не так просто, тому що його використання вимагає деяких тонкощів, які не очевидні на перший погляд.
Перше і, мабуть, найважливіше - це калібрування. Справді, «нейтральний» стан ваших датчиків має місце, коли телефон нерухомий і розміщений на горизонтальній поверхні. Однак більшість часу ви використовуєте свій телефон у портретному режимі, більш-менш обличчям. Тому необхідно провести калібрування, врахувати, що «нейтральне» положення – це те, яке має телефон під час завантаження сторінки, і наївним підходом було б просто зробити віднімання таким чином:

let initialOrientation = null;
window.addEventListener('devicemotion', (eventData) => {
    const r = eventData.rotationRate;
    initialOrientation = initialOrientation || Object.assign({}, r); // first time
    console.log(`
        Angle calibré Alpha : ${r.alpha - initialOrientation.alpha }
        Angle calibré Beta : ${r.beta - initialOrientation.beta}
        Angle calibré Gamma : ${r.gamma -initialOrientation.gamma}
    `);
}, false);

Але як зазначено @yvt в її питання у проекті Gyro.js цей підхід неправильний!
Він пояснює, що Кути Ейлера Використовувані для визначення орієнтації телефону не можна об’єднати, якщо вони діють на дві різні осі простим додаванням або відніманням. І якщо ми хочемо виконати цю маніпуляцію, елегантний спосіб зробити це – використовувати Кватерніони. Я дозволю вам насолоджуватися виконанням калібрування для менш математичних: Об’єднайте запит на витяг
Gyro.js також керує за вас виявленням присутності API HTML5 і додає над ними API «витягування», який дозволяє отримувати останні відомі вимірювання з датчиків за запитом. Дуже практична річ, коли ви використовуєте requestAnimationFrame як ми в продовженні.

Використання Gyro.js

Gyro.js — це більше сценарій, ніж бібліотека, створена Том Галлачер, утиліта включає лише кілька методів і властивостей:

  • gyro.frequency = 500 // періодичність, з якою скрипт викликає зворотний виклик події
  • gyro.getOrientation() // повертає поточні вимірювання
  • gyro.calibrate() // калібрувати отримані вимірювання
  • gyro.startTracking(function(o){…}) // почати періодичний виклик зворотного виклику події
  • gyro.stopTracking() // зупиняємо періодичний виклик зворотного виклику події
  • gyro.hasFeature('devicemotion') // перевіряє, чи підтримує браузер MozOrientation, devicemotion або deviceorientation
  • gyro.getFeatures() // повертає API цих підтримуваних датчиків

Після різних тестів ми отримали найкращий рендеринг, не використовуючи періодичний зворотний виклик, запропонований API Gyro.js, а проходячи через requestAnimationFrame. Це дає можливість плавно асоціювати рух з орієнтацією телефону. Спрощена реалізація цієї концепції виглядає так:

gyro.stopTracking(); // Stop periodic calls
gyro.calibrate(); // Calibrate measurement during the page loading
const speed = 0.01; // A arbitrary speed ...
let lastTimestamp = null;
const refresh = function(timestamp) {
    if (lastTimestamp !== null) { // execute only if timestamp is valued
        const delay = timestamp - lastTimestamp; // duration since the last call
        const o = gyro.getOrientation(); // retrieves the last measures
        const step = speed * delay;
        // Apply step on the background-position in our example, but
        // you can use directly the angles for a CSS rotation property
        // for instance.
    }
    lastTimestamp = timestamp; // save current timestamp for the next call
    window.requestAnimationFrame(refresh); // call for the next refresh (max 60 times per seconde)
};
window.requestAnimationFrame(refresh); // first call

Я настійно рекомендую округлити отримані вимірювання, оскільки вони постійно змінюються,
навіть коли телефон нерухомий. Це дозволить уникнути небажаних ефектів тремтіння або руху.

Кінцевий результат виглядає так:
Переміщення заголовка JS-Republic на мобільний телефон