隨着陀螺儀做爲只能手機的標配,根據手機角度不一樣,讓圖片有點視差微動效果能夠給用戶一點驚喜,因而簡單研究了一下 HTML5 下利用陀螺儀獲取設備方向的 API。javascript
HTML5 中與手機方向變化有關的 API 有兩個,一個是 deviceorientation
事件,一個是 devicemotion
事件。 css
今天這個根據手機動來動去產生微動效果的主要用到 deviceorientation
事件,這個事件主要是監聽並接收設備方向變化信息。
而 devicemotion
事件主要是用來監聽設備在位置和方向上的加速度變化信息,這個主要用在搖一搖等應用上。html
監聽 deviceorientation
事件比較簡單: java
window.addEventListener('deviceorientation', handleFunc, false);複製代碼
而後在回調函數 handleFunc
中會有設備轉過的角度:android
function handleFunc(evnet){
var alpha = event.alpha;
var beta = event.beta;
var gamma = event.gamma;
}複製代碼
這裏的 alpha, beta, gamma 表示的是相對於座標軸,設備在某個給定軸上的旋轉量。ios
另外放上座標系的圖,方便理解:git
光是這樣看可能不太好理解,咱們能夠打開 chrome 開發者工具 Sensors 這一項看看直觀的感覺。程序員
當咱們手機出於直立狀態的時候:github
也就是隻有 beta 值是 90,其它兩個都是 0,能夠本身改下 beta 值,體驗下什麼叫沿 X 軸轉。web
一樣的,沿着 Z 軸轉的 alpha 值,就是相似咱們豎着轉手機。
這樣大概就能理解這三個屬性是表示些什麼東西了,可是這幾個值麻煩的地方是,並不能經過單單一個值來表示出手機向某個方向運動,運動的方向還和手機放置的位置有很大關係。除此以外,還有一個坑是 android 中陀螺儀的數據自己不是很穩定,通常不能直接使用,須要加一些緩衝之類的方法來降噪。
還好,上面那些坑已經有人開始填了,就是 shrekwang 大大作的orienter 組件。
orienter 組件除了提供上面說到的 alpha,beta,gamma 值以外,還另外提供了兩個計算出來的值,分別是 lon 和 lat,字面意思是經度,緯度,能夠大體用來當成平移距離來計算。
咱們來簡單寫個小 demo,隨着手機動,圖片也有一些視差效果,原理是利用 deviceorientation
事件來獲取手機運動方向的改變,而後經過 transform:translate3d(x,y,z)
給設置到圖片上。
首先是 html:
<div class="content">
<img src="../img/test.jpg" class="img"> </div>複製代碼
HTML 比較簡單,咱們只是放個圖片上去。
而後是利用 orienter 組件來實現咱們的功能。
var o = new Orienter();
o.onOrient = function (obj) {
var a, b;
a = obj.lon < 180 ? obj.lon : obj.lon - 360;
b = obj.lat;
a = a > 0 ? a > 50 ? 50 : a : a < -50 ? -50 : a;
b = b > 0 ? b > 50 ? 50 : b : b < -50 ? -50 : b;
$(".img").css("-webkit-transform", "translate3d(" + a + "px," + b + "px,0)");
};
o.init();複製代碼
代碼比較簡單,其中咱們對 lon 值進行了處理,lon 的取值範圍是 0~360,其中,小於 180 的咱們認爲是往右移,大於 180 的當成是往左邊移動,往左的咱們要計算出一個負值。
而後下面有一堆三元運算符用來作判斷,由於咱們平移的距離有一個極限,這裏我設置的是 50。
放上體驗地址:www.imbeta.cn/demo/demos/…
PC 上記得打開 chrome 模擬手機和試試在 Sensors 裏模擬轉向。
最後,orienter 幫咱們作了那麼多事情,固然要大概看下它的源代碼啦。
首先是前面一段是兼容 AMD & CMD 和普通引入的代碼:
(function (factory) {
if (typeof define === 'function' && define.amd) {
define(['exports'], function(exports) {
window.Orienter = factory(exports);
});
} else if (typeof exports !== 'undefined') {
factory(exports);
} else {
window.Orienter = factory({});
}
}(function (Orienter) {
……
……
}複製代碼
以後最重點的是 _orient
方法,其中有個 switch,就是處理咱們上面說的 lon 和 lat 兩個值的計算,還有運動的方向還和手機放置的位置的處理,以及對 android 陀螺儀不穩定的處理。
代碼以下:
switch (this.os) {
case 'ios':
switch (this.direction) {
case 0:
this.lon = event.alpha + event.gamma;
if (event.beta > 0) this.lat = event.beta - 90;
break;
case 90:
if (event.gamma < 0) {
this.lon = event.alpha - 90;
} else {
this.lon = event.alpha - 270;
}
if (event.gamma > 0) {
this.lat = 90 - event.gamma;
} else {
this.lat = -90 - event.gamma;
}
break;
case -90:
if (event.gamma < 0) {
this.lon = event.alpha - 90;
} else {
this.lon = event.alpha - 270;
}
if (event.gamma < 0) {
this.lat = 90 + event.gamma;
} else {
this.lat = -90 + event.gamma;
}
break;
}
break;
case 'android':
switch (this.direction) {
case 0:
this.lon = event.alpha + event.gamma + 30;
if (event.gamma > 90) {
this.lat = 90 - event.beta;
} else {
this.lat = event.beta - 90;
}
break;
case 90:
this.lon = event.alpha - 230;
if (event.gamma > 0) {
this.lat = 270 - event.gamma;
} else {
this.lat = -90 - event.gamma;
}
break;
case -90:
this.lon = event.alpha - 180;
this.lat = -90 + event.gamma;
break;
}
break;
}複製代碼
分別根據 ios/android 平臺對豎屏和左右橫屏作相應處理。
咱們來看下 ios 下的豎屏:
case 0:
this.lon = event.alpha + event.gamma;
if (event.beta > 0) this.lat = event.beta - 90;
break;複製代碼
先看下面那句處理 lat 的,if (event.beta > 0) this.lat = event.beta - 90;
這裏 -90 就是由於豎屏的時候,beta 值默認爲 90。即下面這個圖:
因此這裏 -90 比較好理解。
而後再看上面那句 this.lon = event.alpha + event.gamma;
這裏我想了很久,也沒想出來爲何豎屏的時候 lon 的值是 alpha 和 gamma 之和。
要理解這個,要從咱們日常使用手機的動做來看。現看 gamma 值,gamma 是沿着 y 軸轉動,拿出手機,豎直放置,沿着 y 軸轉一下,手機是這樣的狀態:
這樣的時候咱們通常是要看到更多的左右信息,也就是橫向的經度值,因此手機豎直的時候 gamma 要算到 lon 裏面。
再來看 alpha 值,alpha 值是表示設備沿 Z 軸的變化。要理解這個,咱們要試着想象咱們在拍全景照片。以本身爲圓心,手臂與地面平行,豎着拿着手機,手臂做爲半徑,嘗試像拍攝全景照片,以身體爲圓心,移動手臂。會發現咱們咱們實際上是在作一個圓,而在這途中,手機實際上是沿着 Z 軸在轉動的。
若是以爲說的太抽象,能夠看看下面這個例子,嘗試理解一下。
二維碼:
不少看起來很容易實現的功能,實際上卻有不少不少的坑,要填這些坑,又要有不少積累和思考,對於那些幫你填坑的人,要說一聲『謝謝』。
Demo 源碼地址:github.com/bob-chen/de…
記錄一些所思所想,寫寫科技與人文,寫寫生活狀態,寫寫讀書感悟,主要是扯淡和感悟,歡迎關注,交流。
微信公衆號:程序員的詩和遠方
公衆號ID : MonkeyCoder-Life
developers.google.com/web/fundame…