Cara menggunakan penderia orientasi dalam JavaScript menggunakan Gyro.js

Ketahui dalam artikel ini cara kami hanya menggunakan giroskop dan pecutan dalam penyemak imbas untuk pengepala tapak Republik JS (di bawah mudah alih sudah tentu) terima kasih kepada Gyro.js.

Sedikit peringatan

Tanda tempat telefon XNUMXd
(sumber: http://www.alsacreations.com/tuto/lire/1501-api-device-orientation-motion-acceleration.html)
 
Sebelum memulakan penjelasan tentang penggunaannya dalam penyemak imbas, mari kita lihat dengan cepat apakah penderia ini.
Mudah alih anda menggunakan giroskop untuk mengetahui orientasinya dalam ruang, orientasi ini dinyatakan mengikut alfa, beta dan gamma, tiga sudut putaran dalam darjah di sekeliling paksi Z, X dan Y.pecutan digunakan untuk mengukur pergerakan telefon anda dalam meter/saat² (ukuran pecutan). Jika digabungkan, kedua-dua sensor ini boleh mengukur pecutan putaran peranti.
 
 

Kes (tidak begitu) mudah

Dalam HTML5, terdapat dua API untuk mendapatkan semula ukuran daripada penderia ini, iaitu API orientasi peranti dan juga API devicemotion , yang pertama memulihkan orientasi telefon (alfa, beta, gamma) dan yang kedua juga memulihkan pecutan pergerakan. Pada mulanya, kami boleh mendapatkan semua maklumat yang diperlukan dengan beberapa baris 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);

Memandangkan kesederhanaan API, maka nampaknya tidak perlu menggunakan mana-mana perpustakaan! Nah, ia tidak semudah itu kerana penggunaannya memerlukan beberapa kehalusan yang tidak jelas pada pandangan pertama.
Yang pertama dan mungkin yang paling penting ialah penentukuran. Sesungguhnya, keadaan "neutral" penderia anda berlaku apabila telefon tidak bergerak dan diletakkan rata pada permukaan mendatar. Walau bagaimanapun, kebanyakan masa anda menggunakan telefon anda dalam potret lebih kurang menghadap muka anda. Oleh itu, adalah perlu untuk menjalankan penentukuran, untuk mempertimbangkan bahawa kedudukan "neutral" adalah kedudukan telefon apabila memuatkan halaman dan pendekatan naif adalah dengan hanya membuat penolakan seperti ini:

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);

Tetapi seperti yang dinyatakan @yvt dalam yang isu pada projek Gyro.js, pendekatan ini salah!
Beliau menjelaskan bahawa sudut Euler digunakan untuk memberikan orientasi telefon tidak boleh digabungkan apabila ia bertindak pada dua paksi berbeza dengan penambahan atau penolakan mudah. Dan jika kita ingin melakukan manipulasi ini, cara yang elegan untuk melakukannya adalah dengan menggunakan sukuan. Saya membenarkan anda menikmati pelaksanaan penentukuran untuk yang kurang matematik: Gabungkan permintaan tarik
Gyro.js juga mengurus pengesanan kehadiran API HTML5 untuk anda dan menambahkan API "tarik" di atasnya, yang membolehkan anda mendapatkan semula ukuran terakhir yang diketahui daripada penderia atas permintaan. Perkara yang sangat praktikal apabila anda menggunakan requestAnimationFrame seperti kami dalam sekuel.

Menggunakan Gyro.js

Gyro.js lebih kepada skrip daripada perpustakaan, dicipta oleh Tom Gallacher, utiliti termasuk hanya beberapa kaedah dan sifat:

  • gyro.frequency = 500 // periodicity di mana skrip memanggil panggilan balik acara
  • gyro.getOrientation() // mengembalikan ukuran semasa
  • gyro.calibrate() // menentukur ukuran yang dikembalikan
  • gyro.startTracking(function(o){…}) // mulakan panggilan berkala ke panggilan balik acara
  • gyro.stopTracking() // hentikan panggilan berkala ke panggilan balik acara
  • gyro.hasFeature('devicemotion') // menyemak sama ada penyemak imbas menyokong MozOrientation, devicemotion atau deviceorientation
  • gyro.getFeatures() // mengembalikan API bagi penderia yang disokong ini

Selepas pelbagai ujian, kami memperoleh pemaparan terbaik dengan tidak menggunakan panggilan balik berkala yang dicadangkan oleh API Gyro.js tetapi dengan melalui requestAnimationFrame. Ini memungkinkan untuk mengaitkan pergerakan dengan orientasi telefon dengan cara yang lancar. Pelaksanaan ringkas konsep ini kelihatan seperti ini:

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

Saya amat mengesyorkan untuk membulatkan ukuran yang dikembalikan kerana ia berubah dengan ketara sepanjang masa,
walaupun telefon tidak bergerak. Ini akan mengelakkan kesan goncangan atau gerakan yang tidak diingini.

Hasil akhirnya kelihatan seperti ini:
Mengalihkan pengepala JS-Republic pada mudah alih