有些事我都以忘记,但我现在还记得,今天要写博客,从注册以来,已经隔了3个月没有写(园龄6个月)
这些时间在干嘛,node,grunt,angular,react,phonegap...
今天来扯扯一个好久之前就流行的玩意儿,打开网络,都是前辈们在3 4年前的文章。技术不老,现在看来还是有难度的,尤其做优化响应兼容,更是考验水平
效果图:
大白话:
1.图片全部都是绝对定位absolute,定位技术由js实现
2.盒子之间的间距由内边距实现,我不会告诉你外的box是隐藏的,内边距好计算
3.图的宽度固定,高度自适应,这个没啥可说的
4.列的个数动态计算,可以说是半个自适应,(为啥是半个,因为这个简单版本不会在页面onresize的时候进行整体重绘)
功能:
1.下拉滚动条更新数据
1.1如何捕捉滚动条到达底部判断?
1.2如何进行数据填充
1.3重绘方法(重复使用定位渲染)
2.瀑布流定位渲染
2.1如何进行页面的渲染
2.2如何进行盒子的定位(**重点)
2.3盒子的迭代
0.1 开始
DOM结构,在任何一个现代化的coding上面按下tab键
#content>.box*10>.info>(.pic>img[href=”$$.jpg”])+.title{this ia a title}
0.2 样式(只放大容器,看不见的盒子,内盒子)
#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;} /* 内盒子 */
0.3 休息..休息...
架子搭好了,可喜可贺,以后我要用sass和compass写这该死的样式表,
项目代建有些费力气,create,compass compile,compass watch,
也知道最多写完6行代码,就得ctrl+s一下,那窗口就像啥一样
1.1 窗口到达容器底部判断
思路:混淆点(滚动块底部 && 滚动块顶部 && 滚动块本身)
if (滚动条底部位置 >= 大容器高度offsetHeight){处理}
看似简单,这里有三个函数
// 1 获取当前所有BOX的,class
function getClass (wrap,className){
var obj = wrap.getElementsByTagName('*'); //拿到容器下面是有的标签和类名和ID号
var arr = [];
for(var i=0; i<obj.length;i++){ //遍历这些拿到的东西
if(obj[i].className == className){ //开始筛选,拿到是有的盒子标签
arr.push(obj[i]); //将他push进一个数组里面
}}
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; //返回最后一个盒子的底部距离文档顶部的距离
}
// 3 调用上两个函数,最终得到true OR false ,重点就在这里 function getCheck (){ var documentH = document.documentElement.clientHeight; //文档的高度,单页面等于innerHeight var scrollH = document.documentElement.scrollTop || document.body.scrollTop; //滚动条距离顶部的距离 //加起来实际上就是等于滚动条底部离文档顶部的距离, return documentH + scrollH >= getLastH() ? true:false; //总结:监听滚动事件,如果当前的滚动条位置大于等于最后一个box底部的位置的话返回true };
核心总结:
滚动条顶部位置scrollTop + 网页可视区高度clientHeight = 滚动条底部距网页顶部距离Y
Y >= 最后一个盒子的BOX.offsetTop 得到滚动条到达底部,开始加载数据 & 渲染页面
1.2 如何进行数据填充
一般情况下使用的是JSON或者是数组格式的数据,如何填充?
自己琢磨...
我使用的是二维数组,for循环 + arr[i].src完成取出数据
经过原生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); //创建info var info = document.createElement('div'); info.className = 'info'; box.appendChild(info); //创建pic var pic = document.createElement('div'); pic.className = 'pic'; info.appendChild(pic);};....
1.3 如何进行网页渲染
直接跳到下一个话题,页面渲染话题,因为渲染分为两次,
一次页面加载
二次下拉刷新
三次下拉刷新
四次...
使用的都是同一个大函数
1.99 休息休息,
你以后是微信有看头还是
原生有看头还是
node服务端有看头还是
VR有...
2.1 如何对页面进行渲染
1.计算页面容纳列数
列数 = 页面总宽度clientWidth/单个box盒子的宽度 //列数是不是整数
列数 = Math.floor(页面总宽度clientWidth/单个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); //页面的宽度/第一个box的宽,等于列数 wrap.style.width = boxW * colsNum + 'px'; //外层容器的宽度
2.2 如何进行盒子的定位(重点)
大白话:核心思想是将每一列的BOX高度存储在一个数组中,记住是每一列的
之后获取数组中最小的数字(最矮的那个),盒子定位top = minHeight & left = 数组索引(这真是一个巧妙的设计)
//主函数
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); //页面的宽度/第一个box的宽,等于列数 wrap.style.width = boxW * colsNum + 'px'; //外层容器的宽度 var everyH = []; for (var i=0; i<boxs.length; i++ ){ if(i<colsNum){ everyH[i] = boxs[i].offsetHeight; //首先将第一列的盒子的高度全部存储在数组中 }else{ var minH = Math.min.apply(null,everyH); //求出在数组中最小的那一个, var minIndex = getIndex(minH,everyH); //获得最小高度的那个索引 //将每一个遍历的box设置样式,最小高度的那个就是box的值,最后一个参数不确定是都干啥的 setStyle(boxs[i],minH,boxs[minIndex].offsetLeft,i); //最重要的步骤,小朋友,设置响应盒子的top和leeft值 everyH[minIndex] += boxs[i].offsetHeight; //这里的数组并不会存储所有的值,只是存储列的值,最小列,在不停得更换最小数据 } } };
//获取最小数字的索引
function getIndex (minH,everyH){ //获取索引,遍历所有在数组中的索引值,如果等于最小的那个的话,拿出来
for (index in everyH){
if (everyH[index] == minH){
return index;
}
}
};
//定义盒子的定位style,我引用了jquery
var getStartNum = 0; //设置请求加载的条数
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,已经完成了99%的工作,兴奋吧!!
但是玩转瀑布流可不是一朝一夕的功夫,此版本是一个简单的瀑布流
或许日后会研究强化版的
2.3 如何进行盒子迭代
这一章我主要是为了骗自己的,工作已经完成了!
返回上一个话题1.3应用主函数PBL(‘content’,‘box’);
在最顶端,window.onload = function(){ PBL(‘’content’,‘box’) }
或者$(document).ready(PBL(‘content’,‘box’))
-------算法看不懂,怎么破T_T------
申明:本文中的观点只是博主的观点,不代表博客园的以及其他大神的见解,
如果有疏漏那也是正常的,欢迎各行业大神
前来交流辩驳!