HTML5摇一摇以及音频播放问题优化总结

PHPABC Html5 1,809 次浏览 , , 没有评论

前言感想:不放过任何一个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.x);
  info = info.replace("Y", acceleration.y);
  info = info.replace("Z", 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;
    }
}

参考链接:http://www.html5rocks.com/en/tutorials/device/orientation/
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等手机的使用

    <audio  id="audio" src="http://awp.qq.com/act/a20160315live/shake_sound_male.mp3">
    </audio>
 
    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 moreelements, followed by transparent content that contains no media elements — that is, no

并且:src嵌入的音频的URL。 该URL应遵从 HTTP access controls. 这是一个可选属性;你可以在audio元素中使用 元素来替代该属性指定嵌入的音频。

于是改成第二种方案,解决问题,如下:

    <audio id="audio">   
      <source src="http://ossweb-img.qq.com/images/lol/m/act/a20160315live/shake_sound_male.mp3" type="audio/mpeg">
      Your browser does not support the audio tag.
    </audio>

参考资料:
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/audio
https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/audio
http://www.w3schools.com/html/html5_audio.asp
4. 部分安卓机(如vivo)在微信浏览器里面audio播放不了、没有声音,但是在手机自带的浏览器没问题

解决方案:

```
document.addEventListener('WeixinJSBridgeReady', function () {
 
        audio = document.getElementById("audio");
 
        if (window.DeviceMotionEvent) {
            window.addEventListener('devicemotion', deviceMotionHandler, 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).

参考资料:http://stackoverflow.com/questions/37048438/what-is-this-console-warning-i-keep-getting-deferred-long-running-timer-tasks

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

Go