有些事我都以忘記,但我現(xiàn)在還記得,今天要寫博客,從注冊(cè)以來,已經(jīng)隔了3個(gè)月沒有寫(園齡6個(gè)月)
這些時(shí)間在干嘛,node,grunt,angular,react,phonegap...
今天來扯扯一個(gè)好久之前就流行的玩意兒,打開網(wǎng)絡(luò),都是前輩們?cè)? 4年前的文章。技術(shù)不老,現(xiàn)在看來還是有難度的,尤其做優(yōu)化響應(yīng)兼容,更是考驗(yàn)水平
效果圖:
大白話:
1.圖片全部都是絕對(duì)定位absolute,定位技術(shù)由js實(shí)現(xiàn)
2.盒子之間的間距由內(nèi)邊距實(shí)現(xiàn),我不會(huì)告訴你外的box是隱藏的,內(nèi)邊距好計(jì)算
3.圖的寬度固定,高度自適應(yīng),這個(gè)沒啥可說的
4.列的個(gè)數(shù)動(dòng)態(tài)計(jì)算,可以說是半個(gè)自適應(yīng),(為啥是半個(gè),因?yàn)檫@個(gè)簡(jiǎn)單版本不會(huì)在頁(yè)面onresize的時(shí)候進(jìn)行整體重繪)
功能:
1.下拉滾動(dòng)條更新數(shù)據(jù)
1.1如何捕捉滾動(dòng)條到達(dá)底部判斷?
1.2如何進(jìn)行數(shù)據(jù)填充
1.3重繪方法(重復(fù)使用定位渲染)
2.瀑布流定位渲染
2.1如何進(jìn)行頁(yè)面的渲染
2.2如何進(jìn)行盒子的定位(**重點(diǎn))
2.3盒子的迭代
0.1 開始
DOM結(jié)構(gòu),在任何一個(gè)現(xiàn)代化的coding上面按下tab鍵
#content>.box*10>.info>(.pic>img[href=”$$.jpg”])+.title{this ia a title}
0.2 樣式(只放大容器,看不見的盒子,內(nèi)盒子)
#content{width:auto;height:auto;margin:0 auto;position:relative;}/* 大容器*/.box{width:280px;height:auto;padding:10px;border:none;float:left;} /* 看不見的盒子 */.info{width:280px;height:auto;border-radius:8px;box-shadow: 0 0 11px #666;background:#fff;} /* 內(nèi)盒子 */
0.3 休息..休息...
架子搭好了,可喜可賀,以后我要用sass和compass寫這該死的樣式表,
項(xiàng)目代建有些費(fèi)力氣,create,compass compile,compass watch,
也知道最多寫完6行代碼,就得ctrl+s一下,那窗口就像啥一樣
1.1 窗口到達(dá)容器底部判斷
思路:混淆點(diǎn)(滾動(dòng)塊底部 && 滾動(dòng)塊頂部 && 滾動(dòng)塊本身)
if (滾動(dòng)條底部位置 >= 大容器高度offsetHeight){處理}
看似簡(jiǎn)單,這里有三個(gè)函數(shù)
// 1 獲取當(dāng)前所有BOX的,class
function getClass (wrap,className){ var obj = wrap.getElementsByTagName('*'); //拿到容器下面是有的標(biāo)簽和類名和ID號(hào) var arr = []; for(var i=0; i<obj.length;i++){ //遍歷這些拿到的東西 if(obj[i].className == className){ //開始篩選,拿到是有的盒子標(biāo)簽 arr.push(obj[i]); //將他push進(jìn)一個(gè)數(shù)組里面 }} return arr; }
// 2 function getLastH (){ var warp = document.getElementById('content'); var boxs = getClass(content,'box'); //獲得所有的盒子class return boxs[boxs.length-1].offsetTop + boxs[boxs.length-1].offsetHeight; //返回最后一個(gè)盒子的底部距離文檔頂部的距離 }
// 3 調(diào)用上兩個(gè)函數(shù),最終得到true OR false ,重點(diǎn)就在這里 function getCheck (){ var documentH = document.documentElement.clientHeight; //文檔的高度,單頁(yè)面等于innerHeight var scrollH = document.documentElement.scrollTop || document.body.scrollTop; //滾動(dòng)條距離頂部的距離 //加起來實(shí)際上就是等于滾動(dòng)條底部離文檔頂部的距離, return documentH + scrollH >= getLastH() ? true:false; //總結(jié):監(jiān)聽滾動(dòng)事件,如果當(dāng)前的滾動(dòng)條位置大于等于最后一個(gè)box底部的位置的話返回true };
核心總結(jié):
滾動(dòng)條頂部位置scrollTop + 網(wǎng)頁(yè)可視區(qū)高度clientHeight = 滾動(dòng)條底部距網(wǎng)頁(yè)頂部距離Y
Y >= 最后一個(gè)盒子的BOX.offsetTop 得到滾動(dòng)條到達(dá)底部,開始加載數(shù)據(jù) & 渲染頁(yè)面
1.2 如何進(jìn)行數(shù)據(jù)填充
一般情況下使用的是JSON或者是數(shù)組格式的數(shù)據(jù),如何填充?
自己琢磨...
我使用的是二維數(shù)組,for循環(huán) + arr[i].src完成取出數(shù)據(jù)
經(jīng)過原生DOM添加到大容器中
//不完整的代碼var data = [ {'src':'01.jpg','title':'this is a title'}, {'src':'02.jpg','title':'this is a title'}, {'src':'03.jpg','title':'this is a title'},];....for(i in data){ var box = document.createElement('div'); box.className = 'box'; wrap.appendChild(box); //創(chuàng)建info var info = document.createElement('div'); info.className = 'info'; box.appendChild(info); //創(chuàng)建pic var pic = document.createElement('div'); pic.className = 'pic'; info.appendChild(pic);};....
1.3 如何進(jìn)行網(wǎng)頁(yè)渲染
直接跳到下一個(gè)話題,頁(yè)面渲染話題,因?yàn)殇秩痉譃閮纱危?br>
一次頁(yè)面加載
二次下拉刷新
三次下拉刷新
四次...
使用的都是同一個(gè)大函數(shù)
1.99 休息休息,
你以后是微信有看頭還是
原生有看頭還是
node服務(wù)端有看頭還是
VR有...
2.1 如何對(duì)頁(yè)面進(jìn)行渲染
1.計(jì)算頁(yè)面容納列數(shù)
列數(shù) = 頁(yè)面總寬度clientWidth/單個(gè)box盒子的寬度 //列數(shù)是不是整數(shù)
列數(shù) = Math.floor(頁(yè)面總寬度clientWidth/單個(gè)box盒子的寬度) //向下取整
var wrap = document.getElementById(wrap); //獲得容器 var boxs = getClass(content,'box'); //獲取所有的box var boxW = boxs[0].offsetWidth; var colsNum = Math.floor(document.documentElement.clientWidth/boxW); //頁(yè)面的寬度/第一個(gè)box的寬,等于列數(shù) wrap.style.width = boxW * colsNum + 'px'; //外層容器的寬度
2.2 如何進(jìn)行盒子的定位(重點(diǎn))
大白話:核心思想是將每一列的BOX高度存儲(chǔ)在一個(gè)數(shù)組中,記住是每一列的
之后獲取數(shù)組中最小的數(shù)字(最矮的那個(gè)),盒子定位top = minHeight & left = 數(shù)組索引(這真是一個(gè)巧妙的設(shè)計(jì))
//主函數(shù)function PBL (wrap,box){ var wrap = document.getElementById(wrap); //獲得容器 var boxs = getClass(content,'box'); //獲取所有的box var boxW = boxs[0].offsetWidth; var colsNum = Math.floor(document.documentElement.clientWidth/boxW); //頁(yè)面的寬度/第一個(gè)box的寬,等于列數(shù) wrap.style.width = boxW * colsNum + 'px'; //外層容器的寬度 var everyH = []; for (var i=0; i<boxs.length; i++ ){ if(i<colsNum){ everyH[i] = boxs[i].offsetHeight; //首先將第一列的盒子的高度全部存儲(chǔ)在數(shù)組中 }else{ var minH = Math.min.apply(null,everyH); //求出在數(shù)組中最小的那一個(gè), var minIndex = getIndex(minH,everyH); //獲得最小高度的那個(gè)索引 //將每一個(gè)遍歷的box設(shè)置樣式,最小高度的那個(gè)就是box的值,最后一個(gè)參數(shù)不確定是都干啥的 setStyle(boxs[i],minH,boxs[minIndex].offsetLeft,i); //最重要的步驟,小朋友,設(shè)置響應(yīng)盒子的top和leeft值 everyH[minIndex] += boxs[i].offsetHeight; //這里的數(shù)組并不會(huì)存儲(chǔ)所有的值,只是存儲(chǔ)列的值,最小列,在不停得更換最小數(shù)據(jù) } }};
//獲取最小數(shù)字的索引function getIndex (minH,everyH){ //獲取索引,遍歷所有在數(shù)組中的索引值,如果等于最小的那個(gè)的話,拿出來 for (index in everyH){ if (everyH[index] == minH){ return index; } }};
//定義盒子的定位style,我引用了jqueryvar getStartNum = 0; //設(shè)置請(qǐng)求加載的條數(shù)function setStyle (box,top,left,index){ if (getStartNum >= index) return; $(box).css({ 'position' : 'absolute', 'top' : top, 'left' : left, 'opacity' : '1' }); $(box).stop().animate({ "opacity" : "1" },999); getStartNum = index; //不知道是干啥的}
OK,已經(jīng)完成了99%的工作,興奮吧!!
但是玩轉(zhuǎn)瀑布流可不是一朝一夕的功夫,此版本是一個(gè)簡(jiǎn)單的瀑布流
或許日后會(huì)研究強(qiáng)化版的
2.3 如何進(jìn)行盒子迭代
這一章我主要是為了騙自己的,工作已經(jīng)完成了!
返回上一個(gè)話題1.3應(yīng)用主函數(shù)PBL(‘content’,‘box’);
在最頂端,window.onload = function(){ PBL(‘’content’,‘box’) }
或者$(document).ready(PBL(‘content’,‘box’))
-------算法看不懂,怎么破T_T------
申明:本文中的觀點(diǎn)只是博主的觀點(diǎn),不代表博客園的以及其他大神的見解,
如果有疏漏那也是正常的,歡迎各行業(yè)大神
前來交流辯駁!