一咒吐、繼續(xù)研究scroll事件
上一期我們用scroll事件和相對定位實現(xiàn)了兩欄異速滾動——傳送門带饱。接著往下看岳遥,不得不承認在蘋果的控制下,瀏覽網(wǎng)頁的過程仿佛成了一段奇妙的冒險奠伪,隨著滑塊的滾動役纹,各式各樣的特效總會讓你感到驚喜工秩。我會在這篇文里總結(jié)這些特效的精髓廉白,后面類似的東西就不去一一實現(xiàn)了,以便盡快給大家?guī)砀喔杏玫母韶洝?/p>
二乖菱、圖片懶加載
懶加載很實用坡锡,理解起來又很簡單,從效果上看就是整個頁面的圖片不會一次性加載完成块请,而是滾動條將要滾動到什么位置娜氏,圖片就提前加載到什么位置,相當(dāng)于三碗米飯一頓吃完和分成三頓吃的區(qū)別墩新,大大減少了系統(tǒng)資源的消耗贸弥。怎么實現(xiàn)呢?隨便找一篇相關(guān)博客看看:
$(function(){
var viewportSize = $(window).height();
var lazyload = function(){
var scrollTop = $(window).scrollTop();
$("img").each(function(){
var _this = $(this);
var x = viewportSize + scrollTop + _this.position().top;
if(x>0){
_this.attr("src",_this.attr("loadpic"));
}
})
}
setInterval(lazyload,1000);
})
這段代碼的思路很清晰:每一秒鐘對所有圖片進行一次檢查:如果滾動條滾動到圖片的位置海渊,就加載圖片的src屬性绵疲。這是最容易想到的辦法,但仔細想想臣疑,網(wǎng)頁打開后的每一秒鐘都要把所有的圖片遍歷一次盔憨,是不是有些恐怖?讯沈!至少已經(jīng)加載了src屬性的圖片是不需要再參加遍歷的郁岩,更加恐怖的是不止一篇技術(shù)文章給出了類似的實現(xiàn)方法。想到這里,我似乎找到了這篇水文存在的意義问慎,話不多說萍摊,直接上我的代碼:
const lazyLoad = function (container, src_array, target) { //參數(shù):圖片的父容器,儲存圖片src屬性的數(shù)組如叼,距離圖片多遠則加載圖片
let index = 0;
const pics = container.querySelectorAll("img");
const length = pics.length; //準(zhǔn)備工作
const repeat = function () {
if (pics[index].offsetTop - document.body.scrollTop < target) {
pics[index].setAttribute("src", src_array[index]);
index++;
if (index === length) {
clearInterval(timer);
}
}
}; //核心函數(shù)
const timer = setInterval(function () {
repeat();
}, 200);
};
lazyLoad(column, src_array, 400); //調(diào)用lazyLoad函數(shù)
與第一段代碼最大的不同在于核心函數(shù)repeat冰木,它并沒有直接遍歷所有圖片,而是借用setInterval函數(shù)笼恰,逐個檢查單張圖片是否符合加載的要求:
前提是container里的圖片是依次豎向排列的(橫向排列還玩什么懶加載)踊沸,setInterval會不斷觸發(fā)repeat函數(shù)(當(dāng)然用scroll事件也可以,只不過性能會下降一些)社证。由于index變量初始值為0逼龟,repeat函數(shù)執(zhí)行時會專門判斷第一張圖片是否可以加載,到了加載距離時追葡,第一張圖片加載审轮,index變?yōu)?,此后repeat函數(shù)開始專門對第二張圖片進行檢查辽俗,直到第二張圖片符合加載要求……
如此算來,與第一段代碼相比篡诽,圖片有多少張崖飘,性能就會提升多少倍,老板很開心杈女,但我們并不滿足于此朱浴,如果把repeat函數(shù)中設(shè)置圖片src屬性的代碼換成其他操作,lazyLoad函數(shù)(此時就應(yīng)該換成其他名字了)的普適性不就更強了嗎达椰?
三翰蠢、說換就換
const lazyFn = function (container, target, fn) {
let index = 0;
const contents = container.children;
const length = contents.length;
const repeat = function () {
if (contents[index].offsetTop - document.body.scrollTop < target) {
fn(contents[index])
index++;
if (index === length) {
clearInterval(timer);
}
}
};
const timer = setInterval(function () {
repeat();
}, 200);
};
與上面的懶加載函數(shù)相比,container的子元素不一定非要是img了啰劲,處理函數(shù)也可以通過傳入?yún)?shù)自定義梁沧,這樣MacOS最新發(fā)布的版本圖片鏈接中的很多特效都可以用該函數(shù)來實現(xiàn):
動圖快結(jié)束的時候,div1下面還有很大一段空白蝇裤,再往下拉一點點廷支,div2出現(xiàn)了,并逐漸往上滑動到它本該處的位置栓辜。思路就是給div2的初始樣式設(shè)置為透明度0恋拍,向下偏移一段距離;最終樣式設(shè)置為一個類藕甩,透明度為1施敢,豎向偏移為0,在上面的lazyFn中傳入把這個類賦給div2函數(shù),就可以實現(xiàn)當(dāng)滾動條滾動到一定位置時僵娃,切換div2的樣式概作,最后通過設(shè)置transition添加漸變效果。完整代碼請查看https://github.com/xyst123/lazyFn(內(nèi)附魔性的demo)悯许。