在线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>