瀑布流布局(jquery版本)-- 原生js (vue)实现瀑布流

瀑布流布局的原理

一个页面设定好等宽的元素纵向布局,根据每个元素的高度不同,找出最小高度, 将第二排以后的元素挨个放在下面,实现的效果入下:
在这里插入图片描述

废话不多说, 开始上代码,代码里面每行都有详细的注释

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        html, body{
            overflow: hidden;height: 100%;
        }
        .pubuliu{
            position: relative;
        }
        .pubuliu p{
            position: absolute;
            display: inline-block;
            width: 100px;
            margin: 5px;
            background: #ccc;
            transition: all .3s;
        }
    </style>
</head>
<body>
<div class="pubuliu">
    <p style="width: 100px; height: 100px"></p>
    <p style="width: 100px; height: 70px"></p>
    <p style="width: 100px; height: 150px"></p>
    <p style="width: 100px; height: 250px"></p>
    <p style="width: 100px; height: 80px"></p>
    <p style="width: 100px; height: 90px"></p>
    <p style="width: 100px; height: 120px"></p>
    <p style="width: 100px; height: 210px"></p>
    <p style="width: 100px; height: 230px"></p>
    <p style="width: 100px; height: 100px"></p>
    <p style="width: 100px; height: 70px"></p>
    <p style="width: 100px; height: 150px"></p>
    <p style="width: 100px; height: 250px"></p>
    <p style="width: 100px; height: 80px"></p>
    <p style="width: 100px; height: 90px"></p>
    <p style="width: 100px; height: 120px"></p>
    <p style="width: 100px; height: 210px"></p>
    <p style="width: 100px; height: 250px"></p>
    <p style="width: 100px; height: 80px"></p>
</div>
<script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.js"></script>
<script>
    //列数
    var colCount = 0;

    //定义列高度数组
    var colHeightArry = [];

    //每个 p 的宽度
    var pWidth = $('.pubuliu p').outerWidth(true);

    // 页面上来初始化 p 元素
    function init() {

        //用整个元素的宽度 除以 p的宽度得出列数
        colCount = parseInt($('.pubuliu').width() / pWidth);

        // 便利列数,给列高数组赋值  colHeightArry=[0, 0, 0, 0]
        for(var i = 0 ; i < colCount; i ++){
            colHeightArry[i] = 0
        }

        // p元素一个一个的加载到页面上
        $('.pubuliu p').on('load',function() {
            //定义最小的高度, 取列高数组的第一个值
            var minValue = colHeightArry[0];

            //定义最小高度的下标  0
            var minIndex = 0;

            // 便利列数, 判断列高小于上面定义的最小高度,将当前的列高赋值给最小值,并且重新赋值当前最小值的索引
            for(var i = 0 ; i < colCount; i ++) {
                if(colHeightArry[i] < minValue){
                    minValue = colHeightArry[i];
                    minIndex = i;
                }
            }

            // 开始赋值当前的p元素left和top值
            $(this).css({
                left: minIndex * pWidth,
                top: minValue
            })

            // 将当前的p元素的高度给列高
            colHeightArry[minIndex] += $(this).outerHeight(true)
        })
    }

    init();

    //当窗口大小重置之后,重新执行
    $(window).on('resize',function(){
        reset()
    })


    //当窗口加载完毕,执行瀑布流
    $(window).on('load',function(){
        reset()
    })

    //定义reset函数
    function reset(){
        var colHeightArry= []
        // 计算多少列
        colCount = parseInt($('.pubuliu').width() / pWidth)
        // 赋值列高 colHeightArry
        for(var i = 0 ; i < colCount; i ++){
            colHeightArry[i] = 0
        }

        // 取到p元素集合便利
        $('.pubuliu p').each(function() {

            var minValue = colHeightArry[0]
            var minIndex = 0
            
            for(var i = 0 ; i < colCount; i ++){
                if(colHeightArry[i] < minValue){
                    minValue = colHeightArry[i]
                    minIndex = i
                }
            }

            $(this).css({
                left: minIndex * pWidth,
                top: minValue
            })
            colHeightArry[minIndex] += $(this).outerHeight(true)
        })
    }
</script>
</body>
</html>

原生js(实现瀑布流)

在这里插入图片描述

	const propsValue = reactive({
		list: [
			{ height: 200, background: 'red' },
			{ height: 300, background:'red' },
	        { height: 500, background:'yellow' },
	        { height: 200, background:'blue' },
	        { height: 800, background:'green' },
	        { height: 100, background:'yellow' },
	        { height: 500, background:'green' },
	        { height: 600, background:'red' },
	        { height: 700, background:'red' },
	        { height: 900, background:'yellow' },
	        { height: 200, background:'red' },
	        { height: 300, background:'gray' },
	        { height: 700, background:'gray' },
	        { height: 300, background:'red' },
	        { height: 500, background:'yellow' },
	        { height: 200, background:'blue' },
	        { height: 800, background:'green' },
	        { height: 100, background:'yellow' },
	        { height: 500, background:'green' },
	        { height: 600, background:'red' },
	        { height: 700, background:'red' },
	        { height: 900, background:'yellow' }
		]
	})
	let waterList = reactive<any[]>([])  // 整个元素对象  包含width、height、left、top、background
    let heightList: number[] = []   // 维护一个高度数组
    onMounted(() => {
        const width = 130  // 每个元素的宽度
        const x = document.body.clientWidth  // 可视区域的宽度
        const column = Math.floor(x / width)  // 每一行摆放几个元素

        for (let i = 0; i < propsValue.list.length; i++) {  // 便利所有的元素
            if(i < column) {  // 只找第一行的元素
                // 给第一行的元素设置left和top值
                propsValue.list[i].left = i * width
                propsValue.list[i].top = 20
                waterList.push(propsValue.list[i])
                heightList.push(propsValue.list[i].height)
            }else{  // 第二行开始找
                let current = heightList[0]  // 默认第一个元素是最小的
                let index = 0                // 默认第一个元素是最小的,记录一下索引的位置,方便给元素设置left的值
                heightList.forEach((item, i) => {  // 找第一行已经放好的元素的高度最小的那个元素
                    if(current > item) {  // 找到后面的元素,要是比前面的元素的高度小的话就换当前元素和索引
                        current = item
                        index = i
                    }
                })

                /**   此时 current 是已经排放好的最小元素的高度, index 是已经摆放好的最小元素的索引  **/

                // 找到已经排放好的高度最小的那个元素,赋值给下一个即将要放上去的元素的 left 和 top
                propsValue.list[i].top = current + 40
                propsValue.list[i].left = index * width

                // 找到最小高度元素的位置(已经排放好的) 加上 即将要放上去的元素的高度 重新赋值给当前最小高度 元素的高度
                heightList[index] =  heightList[index] + propsValue.list[i].height + 20

                // 最终放到waterList往页面上渲染
                waterList.push(propsValue.list[i])
            }
        }
    })

弹性和布局折行补元素

效果入下
在这里插入图片描述
实现思想

在mounted里面计算需要补充多少个元素li
const wrap = document.body.clientWidth  // 可视区的宽度
const li = document.querySelectorAll(".cart-li")  // 每个li的宽度
const columnNum = Math.floor(wrap.offsetWidth / li[0].offsetWidth)  // 一行放多少个元素
const num = columnNum - (this.cartList.length % columnNum)  // 渲染的元素个数 余上 一行几个元素,再用一行几个元素 减去 就得出需要补充多少个元素
for(let i = 0; i < num; i++) {
    this.cartList.push({})  // 补充元素(注意: 补充的元素没有id)
}


data里面的数据

data() {
    return{
        // 原始元素有id
		cartList: [
			{id: 1},
			{id: 2},
			{id: 3},
			{id: 4},
			{id: 5},
			{id: 6},
		]
	}
}

样式就用弹性盒布局就行

父元素
.cart{
		display: flex;
        flex-wrap: wrap;
        justify-content: space-between;
}


补充的元素不让他们展示出来,只是占位
.cart-li-none{
     opacity: 0;
 }
 <div class="cart">
     <li :class="item.id ? 'cart-li' : 'cart-li cart-li-none'" v-for="(item, index) in cartList" :key="index">  <!-- 通过有没有id来加class,实现补充的元素不展示,只是占位 -->
         <template v-if="item.id">  <!--里面的内容要是没有id的话也不展示出来-->
             <div class="title">li元素里面的内容</div>
         </template>
     </li>
 </div>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值