zoukankan      html  css  js  c++  java
  • 虎说:简约不简单-瀑布流布局

      有些事我都以忘记,但我现在还记得,今天要写博客,从注册以来,已经隔了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------

    申明:本文中的观点只是博主的观点,不代表博客园的以及其他大神的见解,

    如果有疏漏那也是正常的,欢迎各行业大神

    前来交流辩驳!

  • 相关阅读:
    A good habit is half done
    mysql 练习题
    管理的实践
    mysql 表关联时执行顺序
    python 实现短信轰炸
    python django码云第三方登录
    mysql事务的隔离级别
    微服务
    什么是git
    如何使用Hexo创建博客
  • 原文地址:https://www.cnblogs.com/hu-w/p/5699562.html
Copyright © 2011-2022 走看看