經常我們玩微信都會用到查到附近的人,都是在app上實現手機搖一搖的功能。現在,我們將此技術搬移到手機web上,供大家學習,主要是用到Html5的重要特性就是DeviceOrIEntation:官方文檔
它將底層的方向傳感器和運動傳感器進行了高級封裝,提供了DOM事件的支持。這個特性包括兩種事件:
deviceOrIEntation:封裝了方向傳感器數據的事件,可以獲取手機靜止狀態下的方向數據,例如手機所處角度、方位、朝向等。
deviceMotion:封裝了運動傳感器數據的事件,可以獲取手機運動狀態下的運動加速度等數據。
使用它我們能夠很容易的實現重力感應、指南針等有趣的功能,在手機上將非常有用。例如Opera H5體驗版裡的重力感應球示例就是通過監聽DeviceOrientation API的deviceOrIEntation事件來實現的。
讓我們趕快開始吧!
DeviceMotionEvent(設備運動事件)返回設備有關於加速度和旋轉的相關信息。加速度的數據將包含三個軸:x,y和z(示意如下圖所 示,x軸橫向貫穿手機屏幕或者筆記本鍵盤,y軸縱向貫穿手機屏幕或筆記本鍵盤,z軸垂直於手機屏幕或筆記本鍵盤)。因為有些設備可能沒有硬件來排除重力的 影響,該事件會返回兩個屬性,accelerationIncludingGravity(含重力的加速度)和acceleration(加速度),後者 排除了重力的影響。
我們先來監聽運動傳感事件。
1
2
3
if (window.DeviceMotionEvent) {
window.addEventListener('devicemotion',deviceMotionHandler, false);
}
然後獲取含重力的加速度。
1
2
3
function deviceMotionHandler(eventData) {
var acceleration =eventData.accelerationIncludingGravity;
}
下面就涉及到我們如何計算用戶搖晃手機的原理了。考慮的要點如下:
1、 用戶大多時候都是以一個方向為主晃動手機來進行搖動;
2、 在晃動時三個方向的加速度數據必定都會變化;
3、 我們不能誤判手機正常的運動行為,想一想,如果你的手機放在褲兜裡,走路時它也會有加速度數據變化。
綜上,我們應該針對三個方向的加速度進行計算,間隔測量它們,考察它們在固定時間段裡的變化率,而且需要為它確定一個阈值來觸發動作。
我們需要定義幾個變量來記錄歷史x、y、z軸的數據以及上一次觸發的時間。核心方法實現代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var SHAKE_THRESHOLD = xxx;
var last_update = 0;
var x, y, z, last_x, last_y, last_z;
function deviceMotionHandler(eventData) {
var acceleration =eventData.accelerationIncludingGravity;
var curTime = newDate().getTime();
if ((curTime - lastUpdate)> 100) {
var diffTime = curTime -last_update;
last_update = curTime;
x = acceleration.x;
y = acceleration.y;
z = acceleration.z;
var speed = Math.abs(x +y + z - last_x - last_y - last_z) / diffTime * 10000;
if (speed > SHAKE_THRESHOLD) {
alert("你搖了!");
}
last_x = x;
last_y = y;
last_z = z;
}
}
完整代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<!doctype Html>
<Html>
<head>
<meta charset="utf-8" />
<meta name="vIEwport" content="width=device-width,initial-scale=1.0" />
<title>手機web搖一搖</title>
<script type="text/Javascript" src="jquery-1.11.1.min.JS"></script>
<script type="text/Javascript">
$(function () {
// 定義預准備函數
var imgs = new Array(
'/School/UploadFiles_7810/201603/20160313123731545.gif', // 百度logo
'/School/UploadFiles_7810/201603/20160313123731439.gif', // cnzz logo
'/School/UploadFiles_7810/201603/20160313123731382.png', // QQ logo
'/School/UploadFiles_7810/201603/20160313123731752.gif', // 163logo
'/School/UploadFiles_7810/201603/20160313123731161.png' // 新浪logo
);
// 判斷手機是否運動支持傳感器
if (window.DeviceMotionEvent) {
var speed = 25; // 定義默認加速度,達到這個速度才執行搖一搖
// x,y 表示當前的左邊,
// lastX,lastY 表示搖一搖後最後停留的坐標
var x = y = z = lastX = lastY = lastZ = 0;
// 監聽設備運動事件
window.addEventListener('devicemotion', function () {
var acceleration = event.accelerationIncludingGravity; // 獲取設備的加速度
x = acceleration.x; // 獲取加速度的x軸,用於計算水平水平加速度
y = acceleration.y; // 獲取加速度的y軸,用於計算垂直方向的加速度,同時計算正玄值
// 計算當前的加速度是否大於默認加速度
if (Math.abs(x - lastX) > speed Math.abs(y - lastY) > speed) {
// 搖一搖換logo
$('body').CSS('background', 'url(' + imgs[Math.round(Math.random() * 10) % 5] + ') no-repeat center 120px');
}
// 重新記錄最後一次值,作為下一次開始坐標
lastX = x;
lastY = y;
}, false);
}
})
</script>
</head>
<body>
<div class="picbox" id="picbox"><h1>手機搖一搖,改變LOGO</h1></div>
</body>
</Html>
在手機上打開就可以,別忘了引用jquery,當然可以直接直接修改原生JS。