uniapp 自定义图片预览组件PicturePreview(Vue3、组合式、ts)

组件

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>
相关推荐
好久不见的流星17 分钟前
[基于 Vue CLI 5 + Vue 3 + Ant Design Vue 4 搭建项目] 04 安装 Vue CLI 5
javascript·vue.js·ecmascript
曈欣21 分钟前
vue 控制组件是否显示
前端·javascript·vue.js
nice666601 小时前
CSS的基本语法
java·前端·css·visual studio code
陈在天box1 小时前
《响应式 Web 设计:纯 HTML 和 CSS 的实现技巧》
前端·css·html
爱吃桃子的ICer2 小时前
[UVM]3.核心基类 uvm_object 域的自动化 copy() compare() print() pack unpack
开发语言·前端·ic设计
阿洵Rain3 小时前
【Linux】环境变量
android·linux·javascript
学地理的小胖砸4 小时前
【GEE的Python API】
大数据·开发语言·前端·python·遥感·地图学·地理信息科学
垦利不5 小时前
css总结
前端·css·html
八月的雨季 最後的冰吻5 小时前
C--字符串函数处理总结
c语言·前端·算法
6230_6 小时前
关于HTTP通讯流程知识点补充—常见状态码及常见请求方式
前端·javascript·网络·网络协议·学习·http·html