代理orientationchange事件回调函数

我们在开发Web App时,通常会遇到一些兼容性问题,orientationchange事件就是其中之一。严格来说,并不是orientationchange有兼容问题,而是触发orientationchange事件回调函数时有兼容问题(很绕口啊)。具体表现在回调函数中获取window.innerWidth与window.innerHeight属性上的差异。

在safari下,对orientationchange支持很好,当orientationchange触发回调时,使用window.innerWidth能或立刻获取到最新的屏幕高宽。

而在Android浏览器下,需要延迟一定的时间,才能获取到正确的屏幕高宽。如果触发回调函数时,立刻使用window.innerWidth,那么,只能取到方向未改变之前的高宽,在Android下使用下面的一个简单试验可以得出结果:

<script type="text/javascript">
alert(window.innerWidth); // 默认竖屏状态,得到屏宽480px;
window.addEventListener('orientationchange', function() {
    alert(window.innerWidth); // 触发orientationchange回调时,得到屏宽还是480px;
    setTimeout(function() {
        alert(window.innerWidth); // 延迟300ms,才能得到正确屏宽960px
    }, 300);
}, false);
</script>

 

对于orientationchange的兼容问题,使用proxy函数是很好的一种方法,下面是我给出的一种解决方案:

<script type="text/javascript">
//我的代码库默认依赖了Zepto框架,所以会有Zepto的接口
function createOrientationChangeProxy(fn, scope) {
    return function() {
        /*
         * 如果是Android浏览器,我们设想一种场景,手机从 竖屏-横屏-竖屏-横屏 时,
         * 这个过程经历了四次切换,但实际我们只需要处理最后一次切横屏的结果,
         * 那么,延迟300ms执行回调函数,可以在最开始时清除冗余的orientationChangedTimeout。
         */
        clearTimeout(scope.orientationChangedTimeout);
        var args = Array.prototype.slice.call(arguments, 0);
        scope.orientationChangedTimeout = setTimeout($.proxy(function() {
            /*
             * 再设想一种场景,手机从 竖屏-横屏-竖屏 时,在这个过程,系统并未改变任何东西,
             * 将lastOrientation保存下来,能有效的避免垃圾操作产生的回调处理
             */
            var ori = window.orientation;
            if (ori != scope.lastOrientation) {
                fn.apply(scope, args); // 这里才是真正执行回调函数
            }
            scope.lastOrientation = ori;
        }, scope), $.os.android ? 500 : 0);
    };
}

window.addEventListener('orientationchange', createOrientationChangeProxy(function() {
    alert(window.innerWidth); // 无论是Safari还是Android浏览器都能正确的输出屏宽
}, window), false);
</script>

 

posted on 2013-05-02 18:39  max12  阅读(784)  评论(0编辑  收藏  举报