组件
html
<template>
<view class="preview-container" :style="{display: show ? 'block' : 'none'}">
<view class="f-c-c close" @click="close">
<YcSvgIcon name="close" width="15rpx" height="15rpx" color="#ffffff"></YcSvgIcon>
</view>
<swiper class="swiper" :indicator-dots="true" :autoplay="false" :interval="5000" :duration="500"
:circular="true" @change="onSwiperChange" :current="currentIndex" @transition="scale = 1">
<swiper-item v-for="(image, index) in images" :key="index">
<movable-area scale-area class="movable-area">
<movable-view class="movable-view" :scale="true" :scale-min="1" :scale-max="1" :scale-value="scale"
@scale="onScale" out-of-bounds>
<image class="preview-image" :src="image" mode="aspectFit" @click="close" />
</movable-view>
</movable-area>
</swiper-item>
</swiper>
</view>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const images = ref<Array<string>>([]);
const currentIndex = ref(0);
const show = ref(false);
const scale = ref(1);
function onSwiperChange(e : any) {
scale.value = 1;
currentIndex.value = e.detail.current;
}
const onScale = (e : any) => {
scale.value = e.detail.scale;
console.log(scale.value);
}
const close = () => {
images.value = [];
currentIndex.value = 0;
show.value = false;
}
const previewImage = (imgs : Array<string>, index : number) => {
images.value = imgs;
currentIndex.value = index;
show.value = true;
}
defineExpose({
previewImage,
})
</script>
<style scoped lang="scss">
.preview-container {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
overflow: hidden;
z-index: 99;
background-color: rgba(0, 0, 0, 0.8);
.close {
position: absolute;
top: 25rpx;
right: 25rpx;
z-index: 999;
}
.swiper {
width: 100%;
height: 100%;
.movable-area {
width: 100%;
height: 100%;
.movable-view {
width: 100%;
height: 100%;
}
}
.preview-image {
width: 100%;
height: 100%;
}
}
}
</style>
组件使用
html
<template>
<view class="photography-page view-container">
<YcPicturePreview ref="preview" />
</view>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue';
import YcPicturePreview from "@/components/YcPicturePreview/YcPicturePreview.vue";
let preview = ref<InstanceType<typeof YcPicturePreview>>();
const photos = ref([
{
id: 1,
url: 'https://img2.baidu.com/it/u=1028011339,1319212411&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=313',
selected: false,
},
{
id: 2,
url: 'https://img0.baidu.com/it/u=1668365367,2821596851&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=684',
selected: true,
},
{
id: 3,
url: 'https://img0.baidu.com/it/u=1668365367,2821596851&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=684',
selected: false,
},
{
id: 4,
url: 'https://img0.baidu.com/it/u=1668365367,2821596851&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=684',
selected: false,
},
{
id: 5,
url: 'https://img0.baidu.com/it/u=1668365367,2821596851&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=684',
selected: false,
},
{
id: 6,
url: 'https://img0.baidu.com/it/u=1668365367,2821596851&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=684',
selected: false,
},
{
id: 7,
url: 'https://img0.baidu.com/it/u=1668365367,2821596851&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=684',
selected: false,
},
{
id: 8,
url: 'https://img0.baidu.com/it/u=1668365367,2821596851&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=684',
selected: false,
},
{
id: 9,
url: 'https://img0.baidu.com/it/u=1668365367,2821596851&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=684',
selected: false,
},
{
id: 10,
url: 'https://img0.baidu.com/it/u=1668365367,2821596851&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=684',
selected: false,
},
{
id: 11,
url: 'https://img0.baidu.com/it/u=1668365367,2821596851&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=684',
selected: false,
},
])
const photoUrls = computed(() => {
return photos.value.map(item => item.url)
})
const showBig = (currentIndex : number, list : Array<string>) => {
preview.value?.previewImage(list, currentIndex);
}
</script>
<style lang="scss" scoped>
// ...
</style>