瀑布流,很常见了,淘宝,网易云音乐等等都有,实现原理,咱先放着一遍,先将涉及到的知识点拓展开来css
Math求最小值、最大值,数据库
对于通常的数字直接求,Math.min Math.max 编程
可是求数组呢,一个方法,三种形式,js高程书中利用apply的回调函数,将this指向window,直接将所求的数组做为参数传入json
封装函数的方法数组
封装一个getMin的函数直接调用得到浏览器
var numbers=[23,435,45,34] function getMin(arr){ //封装一个方法 return min=Math.min.apply(null,arr) //利用apply的回调函数,将做用域this指向window,将数组做为参数传入 } console.log(getMin(numbers))
原型对象的方法一app
学过原型对象,直接在Array的原型上添加min方法,让Array拥有min的方法,不推荐,产品化的程序不推荐在基本包装类型添加多余的方法编程语言
Array.prototype.min=function(array){ //直接在原型上添加,传递参数 return Math.min.apply(null,array) } alert(numbers.min(numbers))
原型对象的方法二ide
利用Object.defineProperty方法,这个具体说说函数
Object.defineProperty(Array.prototype,'max',{ writable:false, enumerable:false, configurable:true, value:function(){ return Math.max.apply(null,numbers) } }) console.log(numbers.max())
object.defineProperty()方法直接在对象上定义个新属性或者修改一个对象的现有属性,并返回这个对象
接受三个参数
obj:要在其上定义属性的对象,能够是引用类型Math,也能够是自定义的,或者原型对象
prop:要定义或修改属性的名称(方法名)
descriptor:将被定义或修改属性的描述符
默认状况下使用此方法添加的属性是不可改变的,可是能够设置一些特性使其能够改变,for in 遍历的到等等
对属性添加特性描述有数据描述和存取器描述两种
数据描述
writable:值是否能够重写
enumerable:目标属性是否能够被枚举
value:设置属性的值,能够为任意的数据类型或函数
configurable:目标属性是否能够被删除或修改
//在String原型对象上添加方法 var str='hello' Object.defineProperty(String.prototype,'newword',{ value:'world' }) alert(str.newword) //单独给某个对象添加方法 var obj={} Object.defineProperty(obj,'newword',{ value:'world' }) alert(obj.newword) //完整的特性例子 var obj={} Object.defineProperty(obj,'newword',{ value:'world', writable:false, //是否重写 enumerable:true, //for in 遍历 configurable:true //是否能够删除属性 是否能够再次修改特性 }) alert(obj.newword) //world obj.newword='hello' //writable为false 因此无效 alert(obj.newword) //word for(var i in obj){ console.log(i) //newword enumerable是true能够遍历 } delete obj.newword alert(obj.newword) //undefined 由于删除了
存取器描述
使用
getter方法 得到属性值
setter方法 设置属性值
当使用getter或setter就不容许使用writable和value这两个属性
var obj={} var initValue='hello' Object.defineProperty(obj,'newword',{ get:function(){ return initValue //获得属性值 }, set:function(value){ //设置属性值 initValue=value } }) console.log(obj.newword)
IE8只能在DOM对象上使用的
有趣的东西
Math.min 和 Math.max 方法
var max=Math.max() var min=Math.min() console.log(max>min) //false
这里min反而是大于max呢?
MDN里解释对于
Math.min()若是没有参数,则返回Infinity
Math.max()若是没有参数,则返回-Infinity
任意参数不能转换为数值,则返回NaN
早期的浏览器中不兼容getElementsByClassName 为了获取指定的class元素集合,经常封装一个方法,返回数组
//得到指定class的元素 function getByClass(parent,name){ var lists=parent.getElementsByTagName('*') var arr=[] for(var i=0;i<lists.length;i++){ if(lists[i].className==name){ arr.push(lists[i]) } } return arr }
普通的访问简单,直接,DOM2级为style设置一些属性和方法,好比CSSText,能够直接访问到css元素属性,为元素应用多项变化最快捷的方式,一次性应用全部的
下面的代码,分别是设置CSSText 移除removeProperty length属性帮忙遍历
//访问元素的样式 //DOM2级中规定 CSSText访问style里的代码 var myDiv=document.getElementById('myDiv') myDiv.style.cssText='width:200px;height:200px;background:#fee;color:red;' //移除某个css属性 myDiv.style.removeProperty('color') //遍历css属性 length和item的结合 getPropertyValue方法返回的是css属性值的字符串 for(var i=0;i<myDiv.style.length;i++){ console.log(myDiv.style[i]) }
这里补充个非行间样式的获取方法,直接获取非行间样式是不可读的,返回“”
//获取非行间样式 function getStyle(obj,attr){ if(obj.currentStyle){ return obj.currentStyle[attr] //IE是属性 }else{ return getComputedStyle(obj,false)[attr] //其余为方法 } }
注意:若是是CSSText设置的,普通访问仍是访问的到的,不然仍是用封装函数的方法
json是一种轻量级的文本数据交换格式,是一种数据格式,支持多种编程语言,具备自我描述性,容易理解
JSON: JavaScript Object Notation(JavaScript 对象表示法)
JSON 是存储和交换文本信息的语法。相似 XML。
JSON 比 XML 更小、更快,更易解析。
下面是简单的json格式和遍历
var json={ 'name':'double', 'age':34, 'sex':'man' } // 对于json格式,通常用for in 遍历其中的元素 for(var i in json){ console.log(i) //获得name age sex 得到的是属性 } for(var j in json){ console.log(json[j]) //获得double 34 man 得到的是属性值 }
嵌套的json遍历,
//嵌套的json格式 var json={ 'name':'double', 'age':34, 'sex':{ 'man':'one', 'woman':'two' } } for(var i in json['sex']){ //遍历嵌套的json格式 console.log(i) //属性 console.log(json['sex'][i]) //属性值 }
明天再续写
好吧,如今正式说一说瀑布流的问题,前面都是我在瀑布流中遇到的重要的知识点
下面总结一下思路
瀑布流,两步走
第一步,图片大大小小都对齐,不要溢出,不要塌陷
第二部,滚动鼠标,图片源源不断的来,永远滚不到底
解决第一步:
计算页面中的列数,利用列数求出container的宽度
计算最小图片的高度和索引,让次行的第一张图片到达最小图片的下面,且使得那一行的高度增长
解决第二步:
计算鼠标滚动的距离,相比较最后一张图片的scrollHeight
为新加载的图片建立节点,添加到页面上
附上源码,注释标的挺清楚的
window.onload=function(){ waterFall('container','wrap') //这里获取的是整个的wrap,box则不对,由于padding var dataInt={'data':[{'src':'50.jpg'},{'src':'51.jpg'},{'src':'52.jpg'}]} //数据库中的图片,以json的格式传入 window.onscroll=function(){ if(checkScrollSlide()){ var oParent=document.getElementById('container') for(var i=0;i<dataInt.data.length;i++){ //遍历数据库中的图片 var oWrap=document.createElement('div') //添加新节点到原来的HTML中 oWrap.className='wrap' oParent.appendChild(oWrap) var oBox=document.createElement('div') oBox.className='box' oWrap.appendChild(oBox) var oImg=document.createElement('img') oImg.src='images/'+dataInt.data[i].src oBox.appendChild(oImg) } waterFall('container','wrap') //再次的排序 } } } //排序,让图片大小一致的排序 function waterFall(parent,child){ var iParent=document.getElementById(parent) var aLists=getByClass(iParent,child) //得到class为wrap的图片块 //得到列数 var pageWidth=document.documentElement.clientWidth||document.body.clientWidth var boxWidth=aLists[0].offsetWidth cols=Math.floor(pageWidth/boxWidth) //整个页面/单个宽 //根据列数计算contianer宽度 iParent.style.cssText='width:'+cols*boxWidth+'px;margin:0 auto;' //存放每一行的高度 var colHeight=[] for(var i=0;i<aLists.length;i++){ if(i<cols){ colHeight.push(aLists[i].offsetHeight) //将第一行高度归入 }else{ //其他行 var minH=Math.min.apply(null,colHeight) //利用Math.min查找数组高度最小 var index=colHeight.indexOf(minH) //得到最小的索引 aLists[i].style.position='absolute' //由于移动,因此设置position/top/left aLists[i].style.top=minH+'px' aLists[i].style.left=boxWidth*index+'px' colHeight[index]+=aLists[i].offsetHeight //最小的高度+接下来的高度,使第二小成为最小,而后依次 } } } //获取class为box的元素 传递两个参数parent className function getByClass(parent,name){ var list=parent.getElementsByTagName('*') var arr=[] for(var i=0;i<list.length;i++){ if(list[i].className==name){ arr.push(list[i]) } } return arr } //检测浏览器是否scroll function checkScrollSlide(){ var oParent=document.getElementById('container') var aWrap=getByClass(oParent,'wrap') var lastWrap=aWrap[aWrap.length-1].offsetTop+Math.floor(aWrap[aWrap.length-1].offsetHeight/2) //得到最后一张图片的距离的高度 var scrollTop=document.documentElement.scrollTop||document.body.scrollTop //scrollTop var clientHeight=document.documentElement.clientHeight||document.body.clientHeight //clientHeight if(lastWrap<scrollTop+clientHeight){ //判断 return true } }
但凡是有错,直接指出,相互进步,就立刻也过年了,祝你们新年大吉吧!