这么简单的瀑布流,你确定不看

背景

在工作中我们或多或少都遇到过需要用到瀑布流的列表或者需求,那么我们怎么实现瀑布流呢?今天我就给大家带来一个简单的实现方法。给大家做打个样。

这么简单的瀑布流,你确定不看

技术

  • vue3
  • vite

源码地址

瀑布流地址

后面有时间会将此源码封装成公共组件库–>供大家下载使用–如果大家感兴趣的话可以关注一下

HTML

<template>
  <div>
    <button @click="addCard">增加</button>
    <div class="card">
      <div class="card-list"
      v-waterfall
      v-for="(item,index) in list" :key="index"
      :style="{backgroundColor:item.color,height:item.height}"
      >
        <p class="text"> {{ index }} </p>
      </div>
    </div>

  </div>
</template>

css

这儿注意–>因为在js中我使用的是transform,所以需要使用到定位

.card {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  width: 700px;
}
.card-list {
  position: absolute;
  width: 200px;
}

js

实现逻辑:

  • 声明一个列表的高度数组,保存每列的高度,然后获取最小高度的位置,方便定位过去
  • 自定义指令:v-waterfall–>通过mounted拿取到dom元素
  • 获取每列的最小高度就是你当前元素需要的top值,然后根据最小高度的索引值*宽度=left值
  • 最后将其赋值给transform即可–
  • 然后将高度在此(tabulationHeights)基础上叠加即可下次计算

基本逻辑也就完成了。简单吧

import { onMounted, ref, nextTick } from "vue";

const list = ref([
  {color:'#76da6e',height:'100px'},
  {color:'#40a988',height:'70px'},
  {color:'#2384c4',height:'120px'},
  {color:'#106ba3',height:'80px'},
  {color:'#0a589e',height:'110px'},
  {color:'#0a4e98',height:'90px'},
  {color:'#09408c',height:'100px'},
  {color:'#083680',height:'130px'},
]);
const tabulationHeights = ref([0,0,0,0]);

const updateLayout = (el) => {
  const columns = getMinTabulationHeight(tabulationHeights.value);
  const top = tabulationHeights.value[columns];
  const left = columns * el.clientWidth;
  el.style.transform = `translate(${left}px,${top}px)`;
  tabulationHeights.value[columns] += el.offsetHeight;
}

const getMinTabulationHeight = (arr) =>{
  let min = Math.min(...arr);
  return arr.indexOf(min) !== -1 ? arr.indexOf(min) : 0;
}

const vWaterfall = {
  mounted: (el) => {
    updateLayout(el);
  },
  updated: (el) => {
    // updateLayout(el);
  }
}

// 增加
const addCard = () => {
  // 随机生成高度
  const height = Math.floor(Math.random() * 50 + 100);
  // 随机生成颜色
  const color = '#'+Math.floor(Math.random()*16777215).toString(16);
  list.value.push({color,height:height+'px'});
}

疑问

有朋友可能会问:我列表与列表之间肯定不会没有间隔才对啊!那么请问这个有怎么处理呢?

其实这个很简单,比如你是要封装一个组件的话,你只需要传递一个GAP的值:然后拿到这个间距去参与计算即可:如以下代码

const updateLayout = (el) => {
  const columns = getMinTabulationHeight(tabulationHeights.value);
  const top = tabulationHeights.value[columns] + 20;
  const left = (columns * el.clientWidth) + (columns * 20);
  el.style.transform = `translate(${left}px,${top}px)`;
  tabulationHeights.value[columns] += el.offsetHeight + 20;
}

总结

以上只是一个简单的模板,大家可以在此基础上优化优化以便达到自己需要的要求。今天的分享到这里就结束了哦!下次有好的点在来跟大家分享,如果觉得不错可以收藏哈这个源码库,后续会更新插件库

原文链接:https://juejin.cn/post/7341668771911450651 作者:雾恋

(0)
上一篇 2024年3月4日 上午11:11
下一篇 2024年3月4日 下午4:00

相关推荐

发表回复

登录后才能评论