Vue3+Quasar实现ins风格图片墙

在线Demo:

http://www.arthins.com
源码:https://github.com/hints0816/artblog
在这里插入图片描述

关键要点:
  • 图片墙滚动加载
  • 图片按照1大9小分布
  • 图片间距自适应变化
  • 鼠标悬停图片遮罩层

注:我这里的图片均为正方形

代码实现(具体实现看注释)
template
<template>
<!--Quasar类 内容居中 justify-center -->
  <div class="row justify-center">
  <!--Quasar类 响应式宽度 -->
    <q-page padding class="col-xs-12 col-sm-12 col-md-8 col-lg-6">
    <!--Quasar组件滚动加载 -->
      <q-infinite-scroll @load="onLoad" :offset="200">
      <!--Quasar类 网格间距 -->
        <div :class="outClass + ' row'">
        <!--对不同位置的图片进行样式处理 -->
          <div
            v-for="(src, index) in images"
            :key="index"
            :class="loadClass(index)"
          >
          <!--判断显示大图还是显示小图: 大图 -->
            <template v-if="checkClass(index) == 0 || checkClass(index) == -1">
              <q-img
                @click="getDetail(src.id)"
                @mouseenter="alertNum = index"
                @mouseleave="alertNum = -1"
                :src="src.url"
              >
                <div
                  align="center"
                  v-if="alertNum == index"
                  class="relative-position cursor-pointer indexz"
                >
                  <div
                    class="absolute-center q-col-gutter-x-md"
                    style="font-size: 2em"
                  ></div>
                </div>
              </q-img>
            </template>
            <!--判断显示大图还是显示小图: 小图 -->
            <template v-if="checkClass(index) == 1">
            <!--上小图 -->
              <div class="col-6">
                <q-img
                  @click="getDetail(images[index].id)"
                  @mouseenter="alertNum = index"
                  @mouseleave="alertNum = -1"
                  :src="images[index].url"
                >
                  <div
                    align="center"
                    v-if="alertNum == index"
                    class="relative-position cursor-pointer indexz"
                  >
                    <div
                      class="absolute-center q-col-gutter-x-md"
                      style="font-size: 2em"
                    ></div>
                  </div>
                </q-img>
              </div>
              <!--下小图 -->
              <div class="col-6">
                <q-img
                  v-if="images[index + 1] != undefined"
                  @click="getDetail(images[index + 1].id)"
                  @mouseenter="alertNum = index + 1"
                  @mouseleave="alertNum = -1"
                  :src="images[index + 1].url"
                >
                  <div
                    align="center"
                    v-if="alertNum == index + 1"
                    class="relative-position cursor-pointer indexz"
                  >
                    <div
                      class="absolute-center q-col-gutter-x-md"
                      style="font-size: 2em"
                    ></div>
                  </div>
                </q-img>
              </div>
            </template>
          </div>
        </div>
        <!--Quasar组件滚动加载 -->
        <template v-slot:loading>
          <div class="row justify-center q-my-md">
            <q-spinner-dots color="primary" size="40px" />
          </div>
        </template>
      </q-infinite-scroll>
    </q-page>
  </div>
</template>
script
<script lang="ts">
import { reactive, toRefs, onMounted, getCurrentInstance } from 'vue';
import { Screen } from 'quasar';
import { useRouter } from 'vue-router';
import {
  listArtList,
  getImgContent
} from '../../api/test/index';

export default {
  setup() {
    const { ctx } = getCurrentInstance() as any;
    const router = useRouter() as any;
    let data = reactive({
   	// 控制哪个图片的遮罩层大开
      alertNum: -1,
      // 最外层间距样式
      outClass: Screen.lt.lg
        ? 'q-col-gutter-' + Screen.name
        : 'q-col-gutter-lg',
      // 竖向显示2个图片的样式
      inClass: Screen.lt.lg
        ? 'q-col-gutter-y-' + Screen.name
        : 'q-col-gutter-y-lg',
      images: [],
      imgDetail: null,
      pagesize: 18,
      pagenum: 1,
      total: 18,
    });
    const method = {
    // 判断是否数字工具类
      checkNum(nums: number): boolean {
        const r = /^\+?[0-9][0-9]*$/;
        if (r.test(String(nums))) {
          return true;
        } else {
          return false;
        }
      },
      // Quasar滚动加载调用方法
      async onLoad(index, done): Promise<any> {
        if (data.total > data.pagesize*data.pagenum) {
          data.pagenum += 1;
          const paramss = {
            pagenum: data.pagenum,
            pagesize: data.pagesize,
          };
          let datas = (await listArtList(paramss)) as any;
          setTimeout(() => {
            datas.data.forEach((element: any) => {
              data.images.push({ url: element.imgurl, id: element.ID });
            });
            done();
          }, 2000);
        } else {
          done();
        }
      },
      // 根据图片位置返回class动态改变样式
      loadClass(nums: number): string {
        if (method.checkNum(nums / 9)) {
          if (method.checkNum(nums / 9 / 2)) {
            return 'col-8';
          } else {
            return data.inClass + ' column col-4';
          }
        } else if (method.checkNum((nums - 1) / 9)) {
          if (method.checkNum((nums - 1) / 9 / 2)) {
            return data.inClass + ' column col-4';
          } else {
            return 'nopadding';
          }
        } else if (method.checkNum((nums - 2) / 9)) {
          if (method.checkNum((nums - 2) / 9 / 2)) {
            return 'nopadding';
          } else {
            return 'col-8';
          }
        } else {
          return 'col-4';
        }
      },
      // 根据图片位置判断显示大图还是小图
      checkClass(nums: number): number {
        if (method.checkNum(nums / 9)) {
          if (method.checkNum(nums / 9 / 2)) {
            return 0;
          } else {
            return 1;
          }
        } else if (method.checkNum((nums - 1) / 9)) {
          if (method.checkNum((nums - 1) / 9 / 2)) {
            return 1;
          } else {
            return 2;
          }
        } else if (method.checkNum((nums - 2) / 9)) {
          if (method.checkNum((nums - 2) / 9 / 2)) {
            return 2;
          } else {
            return 0;
          }
        } else {
          return -1;
        }
      },
      // 分页查询
      async listArt(): Promise<any> {
        const paramss = {
          pagenum: 1,
          pagesize: data.pagesize,
        };
        let res = (await listArtList(paramss)) as any;
        res.data.forEach((element: any) => {
          data.images.push({ url: element.imgurl, id: element.ID });
        });
        data.total = res.total
      },
      async getDetail(id: number): Promise<any> {
        let res = (await getImgContent(id)) as any;
        data.imgDetail = res.data;
      }
    };
    // 初始化方法
    onMounted(async () => {
      await method.listArt();
      //监听窗口大小变化事件来改变间距大小
      ctx.$nextTick(() => {
        window.addEventListener('resize', () => {
          if (Screen.lt.lg) {
            (data.outClass = 'q-col-gutter-' + Screen.name),
            (data.inClass = 'q-col-gutter-y-' + Screen.name);
          }
        });
      });
    });
    return {
      ...toRefs(data),
      ...method,
    };
  },
};
</script>
style
<style lang="sass">
.nopadding
  padding: 0px
.indexz
  position: fixed
  top: 0
  left: 0
  bottom: 0
  right: 0
  width: 100%
  height: 100%
  background: rgba(0,0,0,0.8)
</style>

在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值