H5实现摇一摇

前段时间工作饱和度很高,基本上都是 996 的一个节奏,一直没有时间作出一些总结.好在现在工作算是告一段落了,也有时间对之前遇到和解决的问题作一些总结了.

在这段时间的开发中有一个 3d 球,球体上有一些同时可以匹配到的人(如图),那觉得匹配到的人都不合适,就需要换一批,所以加入了摇一摇换一批的功能.demo 点我(只在移动端有效,ios 在微信内打开才有声音)

![201901211040.png](/images/201901211040.png)

当我拿到这个需求的时候,突然就觉得这不就是 H5 所提供的新的 api 吗,之前也一直没有 H5 摇一摇进行实战,现在终于有机会对摇一摇的 api 来实战一波了.自我觉得我代码的注释写得还比较规范,这里直接上代码了.

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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
/*
@name Shake
@desc 摇一摇
@params
options: {
vibrate: boolean 是否开启震动
}
*/

class Shake {
constructor(options) {
this._last = {}; // 前一次摇动的加速度
this._timeout = 1000; // 摇一摇时间间隔
this._lasTime = null; // 最后一次摇动时间
this._callback = null; // 摇一摇事件回调函数
this._vibrates = options.vibrates;
this._isSupport = !!window.DeviceMotionEvent;
}

// 是否支持摇一摇
_isSupport = true;

// 摇一摇处理函数
_handler(event) {
let current = event.accelerationIncludingGravity;
// 部分手机关闭了摇一摇权限功能
if (!current.x && !current.y && !current.z) {
this._isSupport = false;
return;
}

// 只统计100ms 内的加速度改变量
let currentTime = new Date().getTime();
let disTime = currentTime - this._lastTime;
if (disTime > 100) {
// 更新 _lastTime
this._lastTime = currentTime;

//记录上一次设备在x,y,z方向上的加速度
if (!this._last.x && !this._last.y && !this._last.z) {
this._last = {
x: current.x,
y: current.y,
z: current.z,
};
return false;
}

//得到两次移动各个方向上的加速度绝对差距
let disX = Math.abs(this._last.x - current.x);
let disY = Math.abs(this._last.y - current.y);
let disZ = Math.abs(this._last.z - current.z);
let sumSquares = disX * disX + disY * disY + disZ * disZ;
let distance = (Math.sqrt(sumSquares) / disTime) * 10000;
// 如果加速度平方和的平方根大于设定值则触发摇一摇事件
if (distance > 6000) {
if (navigator.vibrate) {
navigator.vibrate(1000);
}
if (this._callback) this._callback();
}

// 更新最后一次摇动加速度
this._last = {
x: current.x,
y: current.y,
z: current.z,
};
}
}

// 是否支持摇一摇
isSupport() {
return this._isSupport;
}

// 开始监听摇一摇
listen(callback) {
this._callback = callback;
if (!this._isSupport) return;
this._lastTime = new Date().getTime();
window.addEventListener(
"devicemotion",
this._handler.bind(this),
false
);
}

// 销毁摇一摇
destroy() {
window.removeEventListener("devicemotion", this._handler);
}
}

export default Shake;

DeviceMotionEventaccelerationIncludingGravity是 h5 所提供的摇一摇的 api,详情请查看DeviceMotionEvent | MDN

vibrate 是 h5 所提供的震动 api,详情请查看Navigator.vibrate() | MDN

然后摇一摇的声音是写回调函数内的,因为我们肯定要请求成功才会给出提示音,不然提示了请求不成功就尴尬了.

可是提示音在 ios 上第一次播放无法通过代码控制,因为 safari 认为自动播放(代码控制)是不安全的,必须要有人机交互才可以播放(摇一摇难道不算人机交互?).没办法,只有在微信签名后进行播放,无论微信签名成功与否都可以触发.

1
2
3
4
5
6
7
8
9
10
11
// 这里的微信签名只是为了ios能顺利播放提示音
window.onload = function () {
wx.config({});
wx.ready(function () {
var circleAudio = document.querySelector("#circleAudio");
if (circleAudio) {
circleAudio.play();
circleAudio.pause();
}
});
};

由于该项目使用的是 vue,所以只提供 vue 的代码一份,其他框架大同小异.代码地址:https://github.com/qiangqiang93/shake

[越努力,越幸运!]