先說一下整體思路
圖片鏈接存儲在
data-lazy中,當(dāng)img移動到屏幕可視區(qū)域后,觸發(fā)loadImg(),將data-lazy賦值給img的src屬性。從而加載圖片。
HTML
<img class="image" src="" data-lazy="http://img.zcool.cn/community/01e3ad554425e20000019ae99db72a.jpg" style="width: 345px; height: 460px;" alt="">
實現(xiàn)方式如下
先監(jiān)聽屏幕的滾動事件調(diào)用
throttle()
window.onscroll = throttle(checkImgs());
throttle()是一個節(jié)流操作,讓高頻連續(xù)觸發(fā)的事件每隔一定的時間長度之后再做出響應(yīng)。是有規(guī)律的時間間隔去執(zhí)行。arguments、apply()
throttle(fn, mustRun = 500) {
var timer = null;
let previous = null;
return function() {
var now = new Date();
var context = this;
var args = arguments;
!previous ? previous = now : '';
var remaining = now - previous;
if (mustRun && remaining >= mustRun) {
fn.apply(context, args);
previous = now;
}
}
}
checkImgs()中處理圖片加載方法是否執(zhí)行;查找并遍歷需要縮放的所有圖片,獲取每個圖片的實際寬度去與屏幕寬度做比較,若大于屏幕寬度則按圖片的實際寬高比縮小圖片,若小于屏幕寬度則居中。
checkImgs() {
var imgs = document.querySelectorAll('.image');
for (let i = this.imgIndex; i < imgs.length; i++) {
//圖片等比縮放為視屏屏幕寬度
var screenWidth = document.getElementsByClassName('text')[0].clientWidth; //圖片最大寬度
var imgWidth = parseFloat(imgs[i].style.width); //圖片實際寬度
var imgHeight = parseFloat(imgs[i].style.height); //圖片實際高度
var aspectRatio = imgWidth/imgHeight; //圖片寬高比
if(imgWidth>=screenWidth){ //圖片寬度大于等于屏幕寬度
imgs[i].style.width=screenWidth+'px';
imgs[i].style.height=screenWidth/aspectRatio+'px';
}else{ //圖片寬度小于屏幕寬度居中
imgs[i].style.margin="0 auto";
}
//調(diào)用圖片加載
this.isInSight(imgs[i])?(this.loadImg(imgs[i]),this.imgIndex = i):'';
}
}
isInSight(el)判斷圖片是否在屏幕區(qū)域內(nèi)。若返回true則觸發(fā)loadImg()加載圖片getBoundingClientRect()用法
isInSight(el) {
var bound = el.getBoundingClientRect(); //獲取元素在頁面位置
var clientHeight = window.innerHeight; //獲取窗口高度
return bound.top <= clientHeight;
}
loadImg()加載圖片,從img的data屬性中提取圖片地址,并賦值給img標(biāo)簽的src,進而觸發(fā)圖片的onload方法。
圖片加載成功不予考慮,若加載失敗的處理為:
1.在圖片的onerror函數(shù)中創(chuàng)建div,用于在圖片加載失敗后替換img標(biāo)簽。內(nèi)容為點擊重新加載
2.給此div添加點擊事件,隱藏div并為img的src屬性重新賦值,進而觸發(fā)圖片重新加載。若圖片加載繼續(xù)失敗,則重新顯示div。
loadImg(el) {
var origin = window.location.origin+window.location.pathname;
if (el.src == origin) {
var source = el.dataset.lazy;
el.src = source;
//圖片加載失敗
el.onerror=function(){
var newItem=document.createElement('DIV');
newItem.className = 'errorImg';
newItem.innerHTML='請點擊重新加載圖片';
newItem.style.cssText="color:#666666;"+"width:"+el.clientWidth+"px;"+"height:"+el.clientHeight+"px;"+"line-height:"+el.clientHeight+"px;"
var parent = el.parentNode;
parent.lastChild == el ? parent.appendChild(newItem) : parent.insertBefore(newItem,el.nextSibling);
// 加載失敗后重新點擊
newItem.onclick=function(){
// el.src=source;
el.src=el.dataset.lazy; //重新為img的src屬性賦值
newItem.style.display='none';
el.style.display='block';
el.onerror=function(){
newItem.style.display='block';
el.style.display='none';
};
}
el.style.display='none';
newItem.style.display='block';
}
}
}