首页>>前端>>JavaScript->手摸手,带你实现移动端H5瀑布流布局

手摸手,带你实现移动端H5瀑布流布局

时间:2023-11-30 本站 点击:0

移动端瀑布流布局是一种比较流行的网页布局方式,视觉上来看就是一种像瀑布一样垂直落下的排版。每张图片并不是显示的正正方方的,而是有的长有的短,呈现出一种不规则的形状。但是它们的宽度通常都是相同的

因为移动端瀑布流布局主要为竖向瀑布流,因此本文所探讨的是竖向瀑布流

特点

竖向瀑布流布局主要有下面几种特点:

一般出现在移动端 H5 页面底部

主要以图片或视频为主

降低页面复杂度,节省空间,可以容纳更多内容

不规则展示,不会那么枯燥,用户体验好

难以或者说不能滚动到页面最底部

不同于传统的分页,瀑布流因为以上这些特点一般被用在这些场景下:

推荐机制下的信息 即根据用户画像推荐或者运营人员推荐的信息

大分类下的信息流 展示的信息有很多,它们的大分类都是相同的,适合用户不明确详细需要获得什么信息或商品的情况下

各个信息或商品之间没有比较强的相关性 和上面一条类似,展示的不是千遍一律的东西,相对独立的信息或商品也许能让用户意外发掘到想要的东西

实现

一般来说主要分为 CSS 实现和 JS 实现

CSS 实现主要是用到一些专门的样式属性,实现起来简单,但是往往会有兼容性问题

JS 实现的方法则不存在这些问题,并且能实现比较个性化的需求,但是实现起来比较麻烦

column 多列布局方法

column 实现瀑布流主要依赖两个属性

column-count 属性是设置共有几列 column-gap 属性是设置每列之间的间隔

column 兼容性

代码

<style>  .pic {    column-count: 3;    column-gap: 5px;  }  .pic .item {    border: 1px solid #ccc;    margin-bottom: 5px;  }  .item img {    width: 100%;  }</style><body>  <div class="pic">    <div class="item">      <!-- 获取 api 取到的图片地址 -->      <img src="" />      <div>001</div>    </div>    ······    <div class="item">      <img src="" />      <div>008</div>    </div>  </div></body>

flex 弹性布局方法

flex 实现瀑布流需要给父元素设置为横向排列。然后通过设置 flex-flow: column wrap 使其换⾏

代码

<style>  .pic {    display: flex;    flex-flow: column wrap;    height: 100vh;  }  .item {    /* 每行展示 3 个 */    width: calc(100%/3 - 5px);    border: 1px solid #ccc;    margin-bottom: 5px;  }  .item img {    width: 100%;  }</style><body>  <div class="pic">    <div class="item">      <!-- 获取 api 取到的图片地址 -->      <img src="" />      <div>001</div>    </div>    ······    <div class="item">      <img src="" />      <div>008</div>    </div>  </div></body>

效果

可以发现图片排序顺序是先垂直方向,然后才是水平方向的。column 多列布局和 flex 弹性布局方法实现的效果图最终相似

JS + 懒加载方法

在不考虑兼容性或者没有特殊图片展示顺序需求下,只是实现瀑布流的话上面两种方案是够用的。如果要实现一些个性化的需求的话,还是得用 JS

主要思路就是:

先将第一行排满

计算第一行的所有图片高度,将第二行第一张图放在第一行最矮的图片后面

进行玩步骤 2,重新计算当前所有列高度,避免步骤 2 添加完成后,该列高度还是最矮

完整代码

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8" />    <meta http-equiv="X-UA-Compatible" content="IE=edge" />    <meta name="viewport" content="width=device-width, initial-scale=1.0" />    <title>JS实现瀑布流</title>    <style>        .item {            box-sizing: border-box;            border: 1px solid #ccc;            position: absolute;            /* 展示为三列,减去间隔宽度 */            width: calc(100% / 3 - 5px);        }        .item img {            width: 100%;        }    </style></head><body>    <div id="pic">        <div class="item">            <img src="..." />            <div>001</div>        </div>        <!-- 剩余图片,实际场景中应该使用for循环 -->        <div class="item">            <img src="..." />            <div>015</div>        </div>    </div></body><script>    var pic = document.getElementById('pic');    var items = pic.children;    // 相邻间距为5像素    var space = 5;    var picAmount = 15;    window.onload = function () {        function getClient() {            return {                width: window.innerWidth ||                    document.documentElement.clientWidth ||                    document.body.clientWidth,                height: window.innerHeight ||                    document.documentElement.clientHeight ||                    document.body.clientHeight,            };        }        function getScrollTop() {            return document.documentElement.scrollTop ||                window.pageYOffset ||                document.body.scrollTop;        }        waterFall();        function waterFall() {            var pageWidth = getClient().width;            var itemWidth = items[0].offsetWidth;            var columns = parseInt(pageWidth / (itemWidth + space));            var picList = [];            for (var i = 0; i < items.length; i++) {                if (i < columns) {                    items[i].style.top = 0;                    items[i].style.left = (itemWidth + space) * i + 'px';                    picList.push(items[i].offsetHeight);                } else {                    // 找到数组中最小高度的那一列,并拿到其下标                    var minHeight = picList[0];                    var index = 0;                    for (var j = 0; j < picList.length; j++) {                        if (minHeight > picList[j]) {                            minHeight = picList[j];                            index = j;                        }                    }                    items[i].style.top = picList[index] + space + 'px';                    items[i].style.left = items[index].offsetLeft + 'px';                    // 操作列的高度 = 当前列原本高度 + 图片的高度 + 相邻的间距                    picList[index] = picList[index] + items[i].offsetHeight + space;                }            }        }        window.onresize = function () {            waterFall();        };        // 监听滚动事件,模拟懒加载        window.onscroll = function () {            // 如果滚动到的位置比当前显示的最后一个图片高,则请求新的图片            if (                getClient().height + getScrollTop() >=                items[items.length - 1].offsetTop            ) {                // 后续的新图片                var datas = [...];                for (var i = 0; i < datas.length; i++) {                    picAmount += 1;                    var div = document.createElement('div');                    div.className = 'item';                    div.innerHTML = `<img src="${datas[i]}" alt=""><div>0${picAmount}</div>`;                    pic.appendChild(div);                }                waterFall();            }        };    };</script></html>

效果

不同于上面两个 css 实现的瀑布流,JS 实现的图片排序顺序是先水平方向,然后才是垂直方向

可以看到当滚动页面的时候,新的图片会不断添加进来,这样就实现懒加载了

总结

如果实现效果简单不考虑兼容的的话可以选择使用 CSS 实现;若要兼容老版本浏览器或者实现一些个性化的需求还是得用 JS 实现

当然除了上文说的这些方法以外,也可以使用第三方库 Masonry 实现

原文:https://juejin.cn/post/7094886507730698270


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:/JavaScript/3964.html