/*
* Author: Alex Gibson
* https://github.com/alexgibson/shake.js
* License: MIT license
*/
(function(global, factory) {
if (typeof define === 'function' && define.amd) {
define(function() {
return factory(global, global.document);
});
} else if (typeof module !== 'undefined' && module.exports) {
module.exports = factory(global, global.document);
} else {
global.Shake = factory(global, global.document);
}
} (typeof window !== 'undefined' ? window : this, function (window, document) {
'use strict';
function Shake(options) {
//feature detect
this.hasDeviceMotion = 'ondevicemotion' in window;
this.options = {
threshold: 15, //默认摇动阈值
timeout: 1000 //默认两次事件间隔时间
};
if (typeof options === 'object') {
for (var i in options) {
if (options.hasOwnProperty(i)) {
this.options[i] = options[i];
}
}
}
//使用date防止重复调用
this.lastTime = new Date();
//accelerometer values
this.lastX = null;
this.lastY = null;
this.lastZ = null;
//创建自定义事件
if (typeof document.CustomEvent === 'function') {
this.event = new document.CustomEvent('shake', {
bubbles: true,
cancelable: true
});
} else if (typeof document.createEvent === 'function') {
this.event = document.createEvent('Event');
this.event.initEvent('shake', true, true);
} else {
return false;
}
}
//重置时间计时器
Shake.prototype.reset = function () {
this.lastTime = new Date();
this.lastX = null;
this.lastY = null;
this.lastZ = null;
};
//开始监听 devicemotion
Shake.prototype.start = function () {
this.reset();
var ua = navigator.userAgent.toLowerCase();
if (this.hasDeviceMotion) {
if (ua.indexOf("like mac os x") > 0) {
// 正则判断手机系统版本
var reg = /os [\d._]*/gi ;
var verinfo = ua.match(reg) ;
var version = (verinfo+"").replace(/[^0-9|_.]/ig,"").replace(/_/ig,".");
var arr=version.split(".");
console.log(arr[0]+"."+arr[1]+"."+arr[2]) //获取手机系统版本
if (arr[0]>12&&arr[1]>2) { //对13.3以后的版本处理,包括13.3
DeviceMotionEvent.requestPermission().then(permissionState => {
if (permissionState === 'granted') { //已授权
window.addEventListener('devicemotion', this, false);//摇一摇
} else if(permissionState === 'denied'){// 打开的链接不是https开头
alert("当前IOS系统拒绝访问动作与方向。请退出微信,重新进入活动页面获取权限。")
}
}).catch((err)=>{
layer.open({
content: '<div style="height: 50px; text-align: center; padding-top: 20px">苹果设备申请摇动权限</div>',
btn: '允许',
// style: 'padding: 50px 30px;',
shadeClose: false,
yes: function(index){
ios13granted();
layer.close(index);
}
})
});
}else{ //13.3以前的版本
window.addEventListener('devicemotion', this, false);
}
} else {
window.addEventListener('devicemotion', this, false);
}
}
};
function ios13granted() {
if (typeof DeviceMotionEvent.requestPermission === 'function') {
DeviceMotionEvent.requestPermission().then(permissionState => {
if (permissionState === 'granted') {
var myShakeEvent = new Shake({
threshold: 12
});
myShakeEvent.start();
window.addEventListener('shake', function () {
start();
}, false); //摇一摇
} else if(permissionState === 'denied'){// 打开的链接不是https开头
alert("当前IOS系统拒绝访问动作与方向。请退出微信,重新进入活动页面获取权限。")
}
}).catch((error) => {
alert("请求设备方向或动作访问需要用户手势来提示")
})
} else {
// 处理常规的非iOS 13+设备
alert("处理常规的非iOS 13+设备")
}
}
//停止监听 devicemotion
Shake.prototype.stop = function () {
if (this.hasDeviceMotion) {
window.removeEventListener('devicemotion', this, false);
}
this.reset();
};
//计算是否触发摇动
Shake.prototype.devicemotion = function (e) {
var current = e.accelerationIncludingGravity;
var currentTime;
var timeDifference;
var deltaX = 0;
var deltaY = 0;
var deltaZ = 0;
if ((this.lastX === null) && (this.lastY === null) && (this.lastZ === null)) {
this.lastX = current.x;
this.lastY = current.y;
this.lastZ = current.z;
return;
}
deltaX = Math.abs(this.lastX - current.x);
deltaY = Math.abs(this.lastY - current.y);
deltaZ = Math.abs(this.lastZ - current.z);
if (((deltaX > this.options.threshold) && (deltaY > this.options.threshold)) || ((deltaX > this.options.threshold) && (deltaZ > this.options.threshold)) || ((deltaY > this.options.threshold) && (deltaZ > this.options.threshold))) {
//calculate time in milliseconds since last shake registered
currentTime = new Date();
timeDifference = currentTime.getTime() - this.lastTime.getTime();
if (timeDifference > this.options.timeout) {
window.dispatchEvent(this.event);
this.lastTime = new Date();
}
}
this.lastX = current.x;
this.lastY = current.y;
this.lastZ = current.z;
};
//事件处理
Shake.prototype.handleEvent = function (e) {
if (typeof (this[e.type]) === 'function') {
return this[e.type](e);
}
};
return Shake;
}));
在页面中创建新实例进行调用
//创建实例
var myShakeEvent = new Shake({
threshold: 12 // 摇动阈值
});
// 监听设备动作
myShakeEvent.start();
//添加一个监听事件
window.addEventListener('shake', function () {
start();
}, false);
IOS端无法使用摇一摇功能,主要方法是对devicemotion的监听
① 必须是https协议,即打开h5页面的链接开头必须是https://… ②
摇一摇功能开启必须经过用户授权,必须用户手动点击确定。
PS:相关H5页面操作,均是在微信浏览器打开
shakejs是一个摇一摇的工具参看https://blog.csdn.net/chclvzxx/article/details/46325053