HTML5設備定向小實踐
- 2019 年 12 月 4 日
- 筆記
本文作者:IMWeb 張穎 原文出處:IMWeb社區 未經同意,禁止轉載
簡介
HTML5的Device API中提供了幾個DOM事件,可以獲得設備的物理方向及運動的資訊,API提供的數據不是來源於原始的感測器資訊,而是來源於設備上的陀螺儀、加速計以及指南針等。
- deviceorientation事件,提供了設備的物理方向資訊,表示為一系列本地坐標系的旋角。
- devicemotion事件,提供了設備的加速資訊,表示為定義在設備上的坐標系中的笛卡爾坐標以及設備在坐標系中的自轉速率。
- 實際上還有另一個事件compassneedscalibration,用於羅盤資訊校準,其瀏覽器支援性較差,就先不討論了。
首先我們來關注一下deviceorientation和devicemotion這兩個事件的兼容性:

只能算是部分支援,所以在使用時,首先需要檢測支援能力,很簡單:
if (window.DeviceOrientationEvent) { window.addEventListener('deviceorientation', function(event) {}, false); } else { alert('本設備不支援deviceorientation事件'); }
if (window.DeviceMotionEvent) { window.addEventListener('devicemotion', deviceMotionHandler, false); } else { alert('本設備不支援devicemotion事件'); }
對於不支援的平台,就不要想太炫酷的效果了,老老實實用觸摸滑動等基礎操作與用戶交互,對於各種動態效果或者交互,我認為第一原則是保證可用且性能良好。
deviceorientation事件
// 註冊一個deviceorientation事件的接收器: window.addEventListener("deviceorientation", function(event) { // 處理event.alpha、event.beta及event.gamma }, true);
event.alpha、event.beta及event.gamma表示設備坐標繫上的旋角,這個角度具體是怎麼理解的呢?先來看看從標準上貼過來的一段話:對於一個移動設備,例如電話或平板,設備坐標系的定義於螢幕的標準方向相關。這意味著類似於鍵盤的滑動元素沒有展開、類似於顯示器的選擇元素摺疊至其默認位置。如果在設備旋轉或展開滑動鍵盤時螢幕方向發生變化,這不會影響關於設備的坐標系的方向。用戶希望獲得這些螢幕方向的變化可以使用現有的orientationchange事件。
這段話的重點是,因為設備坐標系是一個相對的方向坐標系,所以設備旋轉等事件發生後,設備坐標系會根據基準的改變相對應改變。 地球坐標系:
- 東(X)在地面上,垂直於北軸,向東為正。
- 北(Y)在地面上,向正北為正(指向北極)。
- 上(Z)垂直於地面,向上為正。
對於筆記型電腦電腦,設備的坐標系定義於集成鍵盤:
- x在螢幕或鍵盤平面上,螢幕或鍵盤的右側為正。
- y在螢幕或鍵盤螢幕上,螢幕或鍵盤的上方為正。
- z垂直於螢幕或鍵盤螢幕,離開螢幕或鍵盤為正。 旋轉必須使用右手規則,即正向沿一個軸旋轉為從該軸的方向看順時針旋轉。
以兩個坐標系重合為初始狀態,旋轉應用下列規則:
- 以設備坐標系z軸為軸,旋轉alpha度。alpha的作用域為[0, 360)。
- 以設備坐標系x軸為軸,旋轉beta度。beta的作用域為[-180, 180)。
- 已設備坐標系y軸為軸,旋轉gamma度。gamma的作用域為[-90, 90)。
deviceorientation事件提供一個absolute屬性參數,值為true時,提供三個角度絕對值, 為false時,提供任意方向的相對值。
devicemotion事件
// 註冊一個devicemotion時間的接收器: window.addEventListener("devicemotion", function(event) { // 處理event.acceleration、event.accelerationIncludingGravity、 // event.rotationRate和event.interval }, true);
每當設備運動狀態出現加速或者減速時,devicemotio事件都會被觸發。event事件包含acceleration、accelerationIncludingGravity、rotationRate以及interval四個屬性。
- acceleration指定設備相對於地球在x、y與z軸上的加速狀況,可以分別通過其x、y與z屬性進行訪問,單位必須是m/s2。
- accelerationIncludingGravity與acceleration屬性所取的數值相同,但會加上一個加速度相等方向相反的反重力加速度。
- rotationRate指定設備在各個軸上每秒運動多少度。我們可以通過其alpha、beta與gamma屬性訪問rotationRate的各獨立取值,單位必須是deg/s。
- interval指定不同數據獲取操作之間的時間間隔,單位必須是毫秒。並且它必須是一個常量,一旦設定不允許改變。
應用之搖一搖
既然我們可以獲取設備當前的3D角度,並且可以獲得設備在空間中的運動速度,很容易就能想到搖一搖這樣有趣的應用。 搖一搖判斷即判定設備是否有超過加速度變化臨界值的晃動:
if (window.DeviceMotionEvent) { window.addEventListener('devicemotion', shakeEventHandler, false); } else { alert('本設備不支援devicemotion事件'); } var THRESHOLD = 1000; var preX = preY = preZ = x = y = z = 0; var preTime = 0; function shakeEventHandler(event) { var acceleration = event.accelerationIncludingGravity; var curTime = new Date().getTime(); var diffTime = curTime-preTime; if (diffTime > 100) { preTime = curTime; x = acceleration.x; y = acceleration.y; z = acceleration.z; var accelerationDiff = Math.abs(x + y + z - preX - preY - preZ) / diffTime * 10000; if (accelerationDiff > THRESHOLD) { alert("搖一搖有驚喜!"); } preX = x; preY = y; preZ = z; } }