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>
相关推荐
啃火龙果的兔子11 分钟前
前端导出大量数据到PDF方案
前端·pdf
Lj2_jOker19 分钟前
QT 给Qimage数据赋值,显示异常,像素对齐的坑
开发语言·前端·qt
csj5039 分钟前
前端基础之《React(7)—webpack简介-ESLint集成》
前端·react
Jonathan Star39 分钟前
CSS margin 折叠现象的实际代码示例
javascript·css·css3
咚咚咚小柒43 分钟前
【前端】Webpack相关(长期更新)
前端·javascript·webpack·前端框架·node.js·vue·scss
2501_9160088944 分钟前
前端工具全景实战指南,从开发到调试的效率闭环
android·前端·小程序·https·uni-app·iphone·webview
诸葛韩信1 小时前
Webpack与Vite的常用配置及主要差异分析
前端·webpack·node.js
IT_陈寒1 小时前
Vite 5震撼发布!10个新特性让你的开发效率飙升200% 🚀
前端·人工智能·后端
一路向前的月光1 小时前
uniapp(5)滚动列表scroll-view
前端·javascript·uni-app
Hilaku1 小时前
就因为package.json里少了个^号,我们公司赔了客户十万块
前端·javascript·npm