前言感想:不放過任何一個WARNING、ERROR或者不夠好的體驗點,持續不斷優化,精益求精,我們就能夠得到提高。
1. 搖一搖不夠靈敏、搖動很多次沒有響應的問題、
原來搖一搖代碼是從網絡Copy的,活動上線后,發現部分手機搖一搖監測效果不夠靈敏,搖動很多次都沒有響應,恨不得把手機砸了,于是優化。
原搖一搖代碼:
var SHAKE_THRESHOLD = 800;
var last_update = 0;
var x = y = z = last_x = last_y = last_z = 0;
function deviceMotionHandler(eventData) {
var acceleration = eventData.accelerationIncludingGravity;
var curTime = new Date().getTime();
if ((curTime - last_update) > 500) {
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;
var status = document.getElementById("status");
if (speed > SHAKE_THRESHOLD) {
alert('搖一搖顯示');
}
last_x = x;
last_y = y;
last_z = z;
}
}
if(window.DeviceMotionEvent) {
// Mobile browser support motion sensing events
window.addEventListener('devicemotion',deviceMotionHandler,false);
} else {
// Mobile browser does not support the motion sensing events
}
于是開始研究起上面的代碼不夠靈敏的原因,發現:
The device motion event is a superset of the device orientation event; it returns data about the rotation information and also acceleration information about the device. The acceleration data is returned in three axes: x,y and z. They are measured in meters per second squared (m/s^2). Because some devices might not have the hardware to exclude the effect of gravity,the event returns two properties,accelerationIncludingGravity and acceleration,which excludes the effects of gravity,(when this is the case,the acceleration data will be null)
原來HTML5對設備移動有兩個加速度相關的數據:
// Grab the acceleration from the results
var acceleration = eventData.acceleration;
info = xyz.replace("X",acceleration.x);
info = info.replace("Y",acceleration.y);
info = info.replace("Z",acceleration.z);
document.getElementById("moAccel").innerHTML = info;
// Grab the acceleration including gravity from the results
acceleration = eventData.accelerationIncludingGravity;
info = xyz.replace("X",acceleration.z);
document.getElementById("moAccelGrav").innerHTML = info;
于是,優化后代碼如下:
var SHAKE_THRESHOLD = 300,last_update = 0,x = y = z = last_x = last_y = last_z = 0,function deviceMotionHandler(eventData) {
var acceleration = eventData.accelerationIncludingGravity;
var curTime = new Date().getTime();
if ((curTime - last_update) > 500) { //多次移動事件中取兩個點的事件間隔
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 * 1000);
//主要優化點1:原來的計算方式把x、y、z三方向的移動有可能會互相干擾。比如x往真方向,y往負方向,就互相抵消了。
var dist = Math.sqrt((x-last_x)*(x-last_x)+(y-last_y)*(y-last_y)+(z-last_y)*(z-last_y))
var speed = dist/diffTime*10000;
//優化點2:搖動速度測試調整,達到最優
if (speed > SHAKE_THRESHOLD) { //搖一搖靈敏度
alert('搖一搖顯示');
}
last_x = x;
last_y = y;
last_z = z;
}
}
2.頁面報WARNING:The devicemotion event is deprecated on insecure origins,and support will be removed in the future. You should consider switching your application to a secure origin,such as HTTPS.
上面的 devicemotion發現會報如上警告,查了一些資料,目前木有辦法解決,除非切換到https。
3. ERROR: Uncaught (in promise) DOMException: The element has no supported sources.錯誤
原來的插入audio的源碼如下,播放音頻的時候在瀏覽器和調試器的debug環境會報如上錯誤,但是不影響iPhone等手機的使用
function playOrPaused() {
console.log(typeof audio);
console.log(typeof audio.paused);
if (audio.paused) {
audio.play(); //ERROR:Uncaught (in promise) DOMException: The element has no supported sources.
}
}
查閱相關資料發現audio可以支持兩種方式設置src,如下:
1. Permitted content: If the element has a src attribute: zero or more elements,followed by transparent content that contains no media elements — that is,no or elements.
2. Else: zero or more elements,followed by zero or more elements,followed by transparent content that contains no media elements,that is no or elements.
并且:src嵌入的音頻的URL。 該URL應遵從 HTTP access controls. 這是一個可選屬性;你可以在audio元素中使用 元素來替代該屬性指定嵌入的音頻。
于是改成第二種方案,解決問題,如下:
Your browser does not support the audio tag.
4. 部分安卓機(如vivo)在微信瀏覽器里面audio播放不了、沒有聲音,但是在手機自帶的瀏覽器沒問題
```
document.addEventListener('WeixinJSBridgeReady',function () {
audio = document.getElementById("audio");
if (window.DeviceMotionEvent) {
window.addEventListener('devicemotion',false);
} else {
alert('本設備不支持devicemotion事件');
return ;
}
shakeOn(1000);//搖一搖動畫示例
});
```
5. WARNING: Deferred long-running timer task(s) to improve scrolling smoothness. See crbug.com/574343.
setTimeout(function () {
shakeOff();
},n);
在原關閉搖一搖動畫效果中,發現有時候debug調試器反饋如山WARNING,通過查資料發現:
The warning is telling you that your timer wasn’t fired on time because it is a long running callback (> 50ms) and the user was/is about to scroll. While your callback is running,Chrome can’t start scrolling the page so this results in “jank”,user input not being handled in a timely manner. To make the experience better for the user,Chrome decided to postpone firing that callback until a time where running it won’t negatively affect the user.
I don’t know the details of what you’re trying to do,but the correct way to do things would be to chunk up your one big callback into smaller batches and spread them out so that any one call will not noticeably delay user actions. You could additionally look at using requestIdleCallback which will call your function only when Chrome is idle and is ideally suited for non-time critical tasks. (However,requestIdleCallback is supported only on Chrome as of now).