利用grid布局实现瀑布流功能

35 阅读1分钟
<template>
  <div class="container">
    <div class="item" v-for="item in list" :src="item.image" :style="{ 'grid-row': `span ${item.imageSpan + 20 + 6}` }">
      <img :src="item.image" />
      <p class="text">{{ item.text }}</p>
    </div>
  </div>
</template>

<script setup>
import { onMounted, ref } from 'vue';

const list = ref([]);
onMounted(() => {
  const windowWidth = window.innerWidth;
  const res = [
    {
      image: '/image/dog.png',
      text: 'dog'
    },
    {
      image: '/image/boby.png',
      text: 'boby'
    },
    {
      image: '/image/dog2.webp',
      text: 'dog2'
    },
    {
      image: '/image/dog.webp',
      text: 'dog'
    },
    {
      image: '/image/lady.png',
      text: 'lady'
    },
    {
      image: '/image/fox.png',
      text: 'fox'
    },
    {
      image: '/image/dog1.webp',
      text: 'dog1'
    },
  ]
  const ps = res.map(item => {
    return new Promise((resolve) => {
      const img = new Image();
      img.src = item.image;
      img.onload = () => {
        item.imageWidth = img.width;
        item.imageHeight = img.height;
        item.imageSpan = Math.ceil((windowWidth / 2 - 6) / item.imageWidth * item.imageHeight);
        resolve();
      }
    })
  })
  Promise.all(ps).then(() => {
    list.value = res;
  })
})
</script>

<style scoped>
.container {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  grid-auto-rows: 1px;
}

.item {
  display: flex;
  flex-direction: column;
  padding: 3px;
  box-sizing: border-box;
}

img {
  width: 100%;
}

.text {
  background-color: #dedede;
  font-size: 12px;
  color: #000;
  line-height: 20px;
  text-align: center;
}
</style>