瀑布流知识的延伸

瀑布流,很常见了,淘宝,网易云音乐等等都有,实现原理,咱先放着一遍,先将涉及到的知识点拓展开来

一、Math的方法

Math求最小值、最大值,

对于一般的数字直接求,Math.min  Math.max 

但是求数组呢,一个方法,三种形式,js高程书中利用apply的回调函数,将this指向window,直接将所求的数组作为参数传入

封装函数的方法

封装一个getMin的函数直接调用获得

          var numbers=[23,435,45,34]
          function getMin(arr){               //封装一个方法
                return min=Math.min.apply(null,arr)  //利用apply的回调函数,将作用域this指向window,将数组作为参数传入
          }
          console.log(getMin(numbers))

原型对象的方法一

学过原型对象,直接在Array的原型上添加min方法,让Array拥有min的方法,不推荐,产品化的程序不推荐在基本包装类型添加多余的方法

          Array.prototype.min=function(array){     //直接在原型上添加,传递参数
               return Math.min.apply(null,array)
          }
          alert(numbers.min(numbers))

原型对象的方法二

利用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方法

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

二、获取指定class的元素

早期的浏览器中不兼容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是一种轻量级的文本数据交换格式,是一种数据格式,支持多种编程语言,具有自我描述性,容易理解

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])  //属性值
          }

五、关于offsetWidth clientHeight scrollTop相关的总结

明天再续写

六、瀑布流的思路

好吧,现在正式说一说瀑布流的问题,前面都是我在瀑布流中遇到的重要的知识点

下面总结一下思路

瀑布流,两步走

第一步,图片大大小小都对齐,不要溢出,不要塌陷

第二部,滚动鼠标,图片源源不断的来,永远滚不到底

解决第一步

计算页面中的列数,利用列数求出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  
      }
}

但凡有错,直接指出,相互进步,就马上也过年了,祝大家新年大吉吧!

posted @ 2018-02-14 23:15  决起而飞  阅读(887)  评论(0编辑  收藏  举报