
以前写过一篇文章:【jQuery插件】图片延迟加载之jQuery.lazyload,介绍了lazyload的用法和技巧,今天主要探讨在移动端应用的优化。
可视区的计算
通过对window绑定scroll事件,获取被隐藏在可视区域上方的像素数, 再计算img纵向偏移量。当被隐藏在可视区域上方的像素数大于img纵向偏移量+可视区高度时替换img的src。
很多时候业务需要让页面初始化的时候就定位到页面某个位置,前面那样简单的判断会对页头至定位目标位置之间img浪费加载。可以通过getBoundingClientRect()方法获取img相对于视口的位置,从而判断是否需要加载目标图片。
var eLvW, elvH,
var inViewTreshhold = 10;
//...
//inViewTreshhold值可以根据页面是否加载完动态改变大小,当页面加载完的时候增大,也可说页面负担小的时候预加载多一些
eLvW = window.innerWidth + inViewTreshhold;
elvH = window.innerHeight + inViewTre·shhold;
eLnegativeTreshhold = inViewTreshhold * -1;
rect = lazyloadElems[globalLazyIndex].getBoundingClientRect();
//判断是否在可视区域
if ((eLbottom = rect.bottom) >= eLnegativeTreshhold &&
(eLtop = rect.top) <= elvH &&
(eLright = rect.right) >= eLnegativeTreshhold &&
(eLleft = rect.left) <= eLvW &&
(eLbottom || eLright || eLleft || eLtop)) {
//执行加载图片动作
//...
}事件节流
scroll、touchmove、resize事件会触发大量的计算,在低版本Andorid版本浏览器中卡顿甚至崩溃,我们可以简单做一些事件节流的操作。
var eLnow = Date.now();
var lazyEvalLazy = (function() {
var timer, running;
var unblock = function() {
running = false;
};
var run = function() {
clearTimeout(timer);
//执行加载图片动作
//...
setTimeout(unblock);
};
return {
debounce: function() {
clearTimeout(timer);
running = true;
timer = setTimeout(run, 66);
},
throttled: function() {
var delay;
if (!running) {
running = true;
clearTimeout(timer);
delay = Date.now() - eLnow;
if (delay > 300) {
delay = 9;
} else {
delay = 99;
}
timer = setTimeout(run, delay);
}
}
};
})();lazyEvalLazy.debounce用来优化resize事件。lazyEvalLazy.throttled用来优化scroll、touchmove等事件,避免频繁触发。
响应式图片
一般响应式图片解决方案:
img {
max-width: 100%;
height: auto;
}现在<picture>元素好像很有用。假如你的chrome版本是38+,在新标签页打开chrome://flags,勾选’启用实验性网络平台功能enable-experimental-web-platform-features,重启, 查看demo。
目前浏览器对<picture>元素支持的不太好,可以做一些降级处理。
<picture> <source media="(min-width: 1000px)" srcset="http://img.qiang.it/1000x1000"> <source media="(min-width: 500px)" srcset="http://img.qiang.it/500x500"> <source srcset="http://img.qiang.it/100x100"> <img data-sizes="auto" class="lazyload" data-src="http://img.qiang.it/100x100" data-srcset="http://img.qiang.it/240x240 240w, http://img.qiang.it/320x320 320w, http://img.qiang.it/480x480 480w, http://img.qiang.it/768x768 768w, http://img.qiang.it/1000x1000 1000w" alt="不支持picture的时候显示" /> </picture>
用例如window.HTMLPictureElement这样的方法来判断浏览器是是否支持<picture>,对不支持<picture>的元素引入respimage.js,或者直接内置到你lazyload组件里。
if(!window.HTMLPictureElement){
console.log("no picture")
//shiv picture element
document.createElement('picture');
//load respimage polyfill
document.write('<script src="respimage.js"></script>');
}如果全部以iphone为基准做高清图,那么90%以上的手机对服务器端的请求至少多出40%,对服务器和带宽都是巨量的消耗。在无wifi情况下,看的最多的就是菊花转和进度条,根本不能愉快的购物。也许可以这样做:
<img data-srcset="http://img.qiang.it/320x100 1x, http://img.qiang.it/640x200 2x" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==" class="lazyload" />
现在iphone6、iphone6S系列也有了一定的份额,屏幕越来越大,高清图加载越来越吃力。也许可以对这些设备做一些优化:
<img data-srcset="http://img.qiang.it/320x100 1x, http://img.qiang.it/640x200 2x" src="http://img.qiang.it/10x10" class="lazyload" />
先加载一个很小的图片,然后等待高清图像load完毕再替换一下src,这样就有了一个图像模糊到高清的过程,相比空白区域的等待也许会好一些。
事件的监听和触发
通常异步获取数据插入到页面的时候需要再次执行例如$(element).lazyload()这样的方法,这样不利于不了解这个组件的人使用。
我们可以检测window.MutationObserver事件或对document.documentElement绑定DOMAttrModified事件触发lazyload行为。
var element = document.body || document.documentElement;
//lazySizesConfig.mutation为配置选项
if (lazySizesConfig.mutation) {
if (window.MutationObserver) {
new MutationObserver(lazyEvalLazy.throttled).observe(document.documentElement, {
childList: true,
subtree: true,
attributes: true
});
} else {
element.addEventListener("DOMNodeInserted", lazyEvalLazy.throttled, true);
document.documentElement.addEventListener("DOMAttrModified", lazyEvalLazy.throttled, true);
}
}其他事件的监听
//:hover
if (lazySizesConfig.hover) {
document.addEventListener('mouseover', lazyEvalLazy.throttled, true);
}
//:focus/active
document.addEventListener('focus', lazyEvalLazy.throttled, true);
//:target
window.addEventListener('hashchange', lazyEvalLazy.throttled, true);
//:fullscreen
if (('onmozfullscreenchange' in element)) {
window.addEventListener('mozfullscreenchange', lazyEvalLazy.throttled, true);
} else if (('onwebkitfullscreenchange' in element)) {
window.addEventListener('webkitfullscreenchange', lazyEvalLazy.throttled, true);
} else {
window.addEventListener('fullscreenchange', lazyEvalLazy.throttled, true);
}
if (lazySizesConfig.cssanimation) {
document.addEventListener('animationstart', lazyEvalLazy.throttled, true);
document.addEventListener('transitionstart', lazyEvalLazy.throttled, true);
} 

网友评论文明上网理性发言 已有1人参与
发表评论:
评论列表