小c同窗是一名前端程序猿。 這一天,大boss給他下了一個指令:咱們的網站圖片太多太大,太浪費網絡資源了,我要節省流量又不要下降圖片質量,你看着辦吧。 因而,小c同窗想到了圖片懶加載:當圖片沒有出如今用戶屏幕上時,用一張輕量級的佔位圖片代替,圖片出現後用js動態替換爲高質量圖片。 接下來,小c同窗抄起鍵盤開始了敲代碼之旅。。。。。。javascript
要實現圖片懶加載,基本的思路是監聽瀏覽器滾動事件,不斷對比目標元素距離屏幕下方的距離,當目標元素滾動到指定位置時,執行js代碼。html
在不以上三種不一樣的方法在各類瀏覽器下的兼容性各不相同 兼容性表格以下:前端
瀏覽器\獲取滾動高度方法 | window.pageYOffset | document.documentElement.scrollTop | document.body.scrollTop |
---|---|---|---|
chrome | Y | Y | N |
firefox | Y | Y | N |
IE11及以上 | Y | Y | N |
ios | Y | N | Y |
android(wchat+原生瀏覽器) | Y | N | Y |
完整的兼容性代碼java
var supportPageOffset = window.pageXOffset !== undefined;
var isCSS1Compat = ((document.compatMode || "") === "CSS1Compat");
var x = supportPageOffset ? window.pageXOffset : isCSS1Compat ? document.documentElement.scrollLeft : document.body.scrollLeft;
var y = supportPageOffset ? window.pageYOffset : isCSS1Compat ? document.documentElement.scrollTop : document.body.scrollTop;
複製代碼
圖片懶加載是檢測圖片是否進入用戶可見視野,因此選擇window.innerHeight做爲瀏覽器的高度。android
let offsetTop = element.offsetTop; //元素相對body左上角的高度
let scrollTop = getScrollTop().top; //網頁滾動高度
let innerHeight = window.innerHeight; //可用窗口高度
if(offsetTop - scrollTop <= innerHeight){
inViewFun.call(this);
}
複製代碼
該方法的缺點是offsetTop相對父元素來講的,若是目標圖片元素的父元素不是body,則會有問題。ios
var rect = element.getBoundingClientRect();
if((rect && rect.top) <= window.innerHeight ){//進入視野
inViewFun.call(this);
}
複製代碼
完整代碼chrome
function lazyLoad(element, inViewFun, fixedTop, a){
scrollHandler();
if(window.addEventListener){
window.addEventListener('scroll',debounce(scrollHandler));
}else{ //IE
window.attachEvent('scroll',debounce(scrollHandler));
}
//獲取網頁滾動高度
function getScrollTop(){
var supportPageOffset = window.pageXOffset !== undefined;
var isCSS1Compat = ((document.compatMode || "") === "CSS1Compat");
var x = supportPageOffset ? window.pageXOffset : isCSS1Compat ? document.documentElement.scrollLeft : document.body.scrollLeft;
var y = supportPageOffset ? window.pageYOffset : isCSS1Compat ? document.documentElement.scrollTop : document.body.scrollTop;
return {left:x, top:y};
}
// function scrollHandler(){
// let offsetTop = element.offsetTop; //元素相對body左上角的高度
// let scrollTop = getScrollTop().top; //網頁滾動高度
// let innerHeight = window.innerHeight; //可用窗口高度
// if(offsetTop - scrollTop <= innerHeight){
// inViewFun.call(this);
// }
// }
function scrollHandler(){
var rect = element.getBoundingClientRect();
if((rect && rect.top) <= window.innerHeight + fixedTop ){//進入視野
inViewFun.call(this);
}
}
}
複製代碼
圖片懶加載可利用intersection observer, 目前只能在Chrome63+和firefox58+使用 比起事件監聽,Intersection observer用起來比較簡單,可閱讀性也大大提升。開發者只須要註冊一個observer去監控元素而不是寫一大堆亂七八糟的視窗檢測代碼。註冊observer以後咱們只須要作的就是當元素可見時改變它的行爲。瀏覽器
<img class="lazy" src="placeholder-image.jpg" data-src="image-to-lazy-load-1x.jpg" data-srcset="image-to-lazy-load-2x.jpg 2x, image-to-lazy-load-1x.jpg 1x" alt="I'm an image!">
複製代碼
document.addEventListener("DOMContentLoaded", function() {
var lazyImages = [].slice.call(document.querySelectorAll("img.lazy"));
if ("IntersectionObserver" in window) {
let lazyImageObserver = new IntersectionObserver(function(entries, observer) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
let lazyImage = entry.target;
lazyImage.src = lazyImage.dataset.src;
lazyImage.srcset = lazyImage.dataset.srcset;
lazyImage.classList.remove("lazy");
lazyImageObserver.unobserve(lazyImage);
}
});
});
lazyImages.forEach(function(lazyImage) {
lazyImageObserver.observe(lazyImage);
});
} else {
// Possibly fall back to a more compatible method here
}
});
複製代碼