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>
相关推荐
dy171735 分钟前
element-plus表格默认展开有子的数据
前端·javascript·vue.js
2501_915918414 小时前
Web 前端可视化开发工具对比 低代码平台、可视化搭建工具、前端可视化编辑器与在线可视化开发环境的实战分析
前端·低代码·ios·小程序·uni-app·编辑器·iphone
2501_915106325 小时前
iOS 使用记录和能耗监控实战,如何查看电池电量消耗、App 使用时长与性能数据(uni-app 开发调试必备指南)
android·ios·小程序·uni-app·cocoa·iphone·webview
程序员的世界你不懂5 小时前
【Flask】测试平台开发,新增说明书编写和展示功能 第二十三篇
java·前端·数据库
索迪迈科技5 小时前
网络请求库——Axios库深度解析
前端·网络·vue.js·北京百思可瑞教育·百思可瑞教育
gnip5 小时前
JavaScript二叉树相关概念
前端
一朵梨花压海棠go6 小时前
html+js实现表格本地筛选
开发语言·javascript·html·ecmascript
attitude.x6 小时前
PyTorch 动态图的灵活性与实用技巧
前端·人工智能·深度学习
β添砖java6 小时前
CSS3核心技术
前端·css·css3
空山新雨(大队长)6 小时前
HTML第八课:HTML4和HTML5的区别
前端·html·html5