zoukankan      html  css  js  c++  java
  • web瀑布流式布局(解决div等宽不等高,实现紧挨效果)

    为什么要有瀑布流:

    由于div高度不一样,不管是左浮动还是inline-block,同级的div都会平行显示(会有空白部分)。

    没有加的效果:

    加了瀑布流效果样子:

    瀑布流实现方式:

    1. css + js (难点) :  需要通过js计算图片的位置,进行正确排放,顺序不会乱,可持续加载新的数据

    2. 纯css(简单) : 数据排序方式是列排序的,当有新的数据持续加载进入不合适,但是性能高、简单

    视频教程:

    # 慕课网的 瀑布流布局教程视频

    https://www.imooc.com/learn/101

    第一种方法:

    思路: 首先瀑布流的特点是 等宽不等高,需要获取到盒子的宽度,计算出多少列,拿到第一行每个盒子的高度数组,从第二行第一个开始,依次找最矮盒子的高度位置进行位置偏移即可,之后累加列高度,从而使整个页面的盒子紧挨。

      1 <!DOCTYPE html>
      2 <html lang="en">
      3 <head>
      4   <meta charset="UTF-8">
      5   <title>Title</title>
      6   <style>
      7     body{
      8       padding: 0;
      9       margin: 0;
     10     }
     11     #pb_main{
     12       position: relative;
     13     }
     14     #pb_main .box{
     15       width: 15.6%;
     16       padding: 0.5em;
     17       float: left;
     18     }
     19     #pb_main .box .box-content{
     20       border: 1px solid #aaa;
     21       border-radius: 1em;
     22       overflow: hidden;
     23       box-shadow: 0 0 20px #ccc;
     24     }
     25     #pb_main .box .box-content:hover{
     26       cursor: pointer;
     27       transition: 0.2s;
     28       transform: translateY(-5px);
     29     }
     30     #pb_main .box .box-content .picture{
     31     }
     32     #pb_main .box .box-content .picture img{
     33       width: 100%;
     34     }
     35     #pb_main .box .box-content .pb-text{
     36       padding: 5px;
     37     }
     38 
     39   </style>
     40 </head>
     41 <body>
     42   
     43   <div id="pb_main">
     44 
     45   </div>
     46 
     47 <script>
     48 
     49   let img_index = 0;
     50 
     51   // 批量添加一些,第一批测试数据
     52   function addElement(count) {
     53     let pb_main = document.getElementById('pb_main');
     54     for (let i=0;i<count;i++,img_index++){
     55       let box = document.createElement('div');
     56       box.classList.add('box');
     57       let boxContent = document.createElement('div');
     58       boxContent.classList.add('box-content');
     59       let picture = document.createElement('div');
     60       picture.classList.add('picture');
     61       let img = document.createElement('img');
     62       img.src = `image/${img_index+1}.jpg`;
     63       let pgText = document.createElement('div');
     64       pgText.classList.add('pb-text');
     65       pgText.innerText = `${(i+1)*123}测试标题~~`;
     66 
     67       picture.appendChild(img);
     68       boxContent.appendChild(picture);
     69       boxContent.appendChild(pgText);
     70       box.appendChild(boxContent);
     71       pb_main.appendChild(box);
     72 
     73       // 每加载好一个图片,就执行重新布局一遍。
     74       img.onload = function () {
     75         waterfall('pb_main', 'box')
     76       };
     77     }
     78 
     79   }
     80 
     81   function getArrayIndex(arr, value) {
     82     for (let i=0;i<arr.length;i++){
     83       if (arr[i] === value){
     84         return i;
     85       }
     86     }
     87   }
     88 
     89   // 排版瀑布流,思路:第二行第一个元素跟着第一行高度最矮的,依次类推。
     90   function waterfall(parent, box){
     91     // 获取标签对象
     92     let Parent = document.getElementById(parent);
     93     let boxes = Parent.getElementsByClassName(box);
     94     // 获取盒子的宽,瀑布流的特点:等宽不等高
     95     let boxWidth = boxes[0].offsetWidth;
     96     // 获取屏幕能有几列盒子数
     97     let cols = Math.floor(document.body.clientWidth / boxWidth);
     98     // 存放列高
     99     let temp = [];
    100     // 循环修改盒子的位置
    101     for (let i=0;i<boxes.length;i++){
    102       // 第一行不做位置修改,要记录高度,再后续行修改完位置后需要累加高度
    103       // 第二行、第三行。。。根据temp表里记录的高度,找出最矮的依次排序到下面
    104       if (i < cols){
    105         temp.push(boxes[i].offsetHeight);
    106       }else{
    107         // 查找最小的高度
    108         let height = Math.min(...temp);
    109         // 最小高度的索引
    110         let index = getArrayIndex(temp, height);
    111         // 修改当前循环盒子的页面位置
    112         boxes[i].style.position = "absolute";
    113         boxes[i].style.left = `${boxWidth * index}px`;
    114         boxes[i].style.top = `${height}px`;
    115         // 累加高度列表的该索引的值
    116         temp[index] += boxes[i].offsetHeight;
    117         // 设置父级高度,这样布局不会乱,由于左浮动后没有高度
    118         Parent.style.height = `${Math.max(...temp)}px`
    119       }
    120     }
    121   }
    122 
    123   // 检查高度是否超过
    124   function checkScrollTop(parent, box){
    125     // 滚动条顶部的值
    126     let top = document.documentElement.scrollTop||document.body.scrollTop;
    127     let screen_height = document.documentElement.clientHeight || document.body.clientHeight;
    128     // 获取标签对象
    129     let Parent = document.getElementById(parent);
    130     let boxes = Parent.getElementsByClassName(box);
    131     let last_box = boxes[boxes.length-1];
    132     let last_box_h = last_box.offsetTop + Math.floor(last_box.offsetHeight / 2);
    133     console.log(`最后盒子顶部距离 + 它一半高度:${last_box_h}, 顶部距离加屏幕高度是: ${top+screen_height}`);
    134     // 判断顶部滚轮+屏幕高度是否大于这个最后盒子距离+一半高度, 大于表示要加载新内容了
    135     return (top+screen_height) > last_box_h  ? true:false;
    136   }
    137 
    138   window.onload = function (){
    139     // 添加首次的测试元素,需要大于一屏幕
    140     addElement(20);
    141     // 监测滚动条
    142     window.onscroll = function () {
    143       // 判读是否需要加载新内容
    144       if (checkScrollTop('pb_main', 'box')){
    145         addElement(10);
    146         // 由于图片有限,重置
    147         if (img_index >= 29){
    148           img_index = 0;
    149         }
    150       }
    151     }
    152   }
    153 
    154 </script>
    155 </body>
    156 </html>
    View Code

    // 图片素材自己找点(30张图片),就可以看运行效果了

    第二种方法:

      .my-card-wrapper{
        -moz-column-count:2;
        -webkit-column-count:2;
        column-count:2;
        -moz-column-gap:0;
        -webkit-column-gap:0;
        padding-top: 0.5em;
      }
    
    
      .my-card{
        border: 1px solid #cccccc;
        padding: 8px;
        border-radius: 10px;
        -moz-page-break-inside: avoid;
        -webkit-column-break-inside: avoid;
        break-inside: avoid;
        margin: 0 0.5em 0.5em;
      }

    // 斜体加粗部分是关键代码

     代码解释:

    column-count   # 流式布局几列显示
    -moz-column-count:2;     # 为了适配不同浏览器
    -webkit-column-count:2;  # 为了适配不同浏览器
    -webkit-column-gap:0;  # 列之前的间隔,有默认间隔值,为了不影响效果,我改的0,自己做边距
    break-inside: avoid;  # 防止多列布局,分页媒体和多区域上下文中的意外中断?? 不懂设置上即可
     
  • 相关阅读:
    Prototype.doc in Netsuite
    中文编码问题(utf8转为中文)
    js 取得 Unix时间戳(Unix timestamp)
    关于'跳墙'
    webex js 判断是否是ie 以及兼容性代码
    VLOOKUP函数对查找内容列排序增加效率
    netsuite动态绑定事件
    netsuite filter的选择框 代码控制
    html js 跨域 p3p
    netsuite 记录类型 权限分配 use permissions
  • 原文地址:https://www.cnblogs.com/zezhou/p/13196227.html
Copyright © 2011-2022 走看看