需求要求实现页面点击按钮摇一摇或者摇一摇手机触发抽奖。
页面会展示在微信小程序+APP中;
我在网络上找了一些方法,微信sdk中并未提供摇一摇的方法给H5页面调用,所以我采取以下方法:
h5代码判断运行环境是APP还是非APP
1.APP内
保险起见,调用APP提供给H5这边的摇一摇方法(要和APP端的开发人员协商),h5直接调用方法,摇一摇触发之后要关闭这个摇一摇方法,不然抽完奖之后摇一摇手机还是会触发。
2.非APP内
使用shake.js,代码如下:
/** 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 detectthis.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 valuesthis.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;};//开始监听 devicemotionShake.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.3DeviceMotionEvent.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+设备")}
}//停止监听 devicemotionShake.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 registeredcurrentTime = 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;
}));
在h5页面内引入
<script type="text/javascript" src="shake.js"></script>
//创建实例var myShakeEvent = new Shake({threshold: 12 // 摇动阈值});// 监听设备动作myShakeEvent.start();//添加一个监听事件window.addEventListener('shake', function () {// start();console.log('摇一摇')}, false);
注意:
1、本地联调的时候这个方法不会触发,因为h5页面的链接开头必须是https://…才会触发(这个特别坑),而且微信调整了政策了,h5页面的链接必须使用ssl加密的证书。
2、在ios13.3之前的版本中可以触发摇一摇,之后的版本需要兼容,需要制作一个让用户能手动点击的弹框,才能使用户授权动作与方向的权限。(需使用https协议)
如果实在不触发,那就让设计师增加一个点一点的样式,晃动手机实在不触发那就通过点一点触发
3.关于摇一摇音效
如果是调用的APP抛出的方法,那可能是自带音效的(要看APP开发人员是怎么定义的方法)
不是调用的APP抛出的方法的话,那可以通过以下方式触发:
音效:https://download.csdn.net/download/tt18473481961/87512465
<audio preload="" id="sing"><source src="images/sing.mp3" type="audio/mp3"></audio>#sing {display: none;
}var sing=document.getElementById("sing");sing.play();