当前位置: 首页 > article >正文

uniapp 做一个查看图片的组件,图片可缩放移动

因为是手机端,所以需要触摸可移动,双指放大缩小。

首先在components里建个组件

查看图片使用 uni-popup 弹窗

要注意 transform的translate和scale属性在同一标签上不会一起生效

移动就根据触摸效果进行偏移图片

缩放就根据双指距离的变大变小进行缩放

<template>
	<view>
		<uni-popup style="z-index: 99998;" ref="showImage" type="center">
			<view :style="{'transform':'translate('+x+'px,'+y+'px)'}">
				<img
					:style="{'transform':'scale(' + scale +')','height': height + 'px'}"
					@touchstart="touchstart"
					@touchmove="touchmove"
					@touchend="touchend"
					@touchcancel="touchcancel"
					mode="aspectFit"
					:src="src"></img>
			</view>
			<view class="closePopup" @click="close">
				<uni-icons type="closeempty" size="32" color="#fff"></uni-icons>
			</view>
		</uni-popup>
	</view>
</template>

<script>
	export default {
		name:"selectImage",
		data() {
			return {
				height: 0,
				src: '',
				x: 0,
				y:0,
				clientX: 0,
				clientY: 0,
				moveX: 0,
				moveY: 0,
				touchType: 0, // 0为单指触摸  1为双指
				// 初始双指距离
				distance: 0,
				// 初始缩放比例
				scale: 1
			};
		},
		created() {
			const me = this
			uni.getSystemInfo({
				success(res) {
					// 默认图片高度占屏幕一半展示
					me.height = res.windowHeight / 2
				}
			})
		},
		methods: {
			// 获取两点距离
			getDistance (point1, point2) {
				const x = point1.clientX - point2.clientX
				const y = point1.clientY - point2.clientY
				return Math.sqrt(x*x + y*y)
			},
			// 触摸开始
			touchstart (e) {
				// 当触摸事件为一个时
				if (e.touches.length === 1) {
					// 记录开始触摸位置
					this.clientX = e.changedTouches[0].clientX
					this.clientY = e.changedTouches[0].clientY
					this.touchType = 0
				} else if (e.touches.length === 2) {
					// 双指进行放大缩小操作
					this.touchType = 1
					// 获取双指距离
					this.distance = this.getDistance(e.touches[0], e.touches[1])
				}
			},
			// 触摸移动中
			touchmove (e) {
				// 当触摸事件为一个时
				if (this.touchType === 0) {
					// 记录移动的距离 
					const moveX = e.changedTouches[0].clientX - this.clientX
					const moveY = e.changedTouches[0].clientY - this.clientY
					// 最终偏移距离为初始偏移距离+当前偏移距离
					this.x = this.moveX + moveX
					this.y = this.moveY + moveY
				} else if (this.touchType === 1) {
					// 双指进行放大缩小操作
					if (e.touches.length === 2) {
						// 获取移动后的双指距离
						const le = this.getDistance(e.touches[0], e.touches[1])
						// 最终放大 缩小效果为 初始放大缩小比例 * 当前放大缩小比例
						const bl = le / this.distance
						const scale = this.scale * bl
						this.scale = scale > 0.1 ? scale : 0.1
						// 随着移动将开始的位置重置 不然会一次性放很大 或者缩很小,不好控制
						this.distance = le
					}
				}
			},
			// 触摸结束
			touchend (e) {
				// 当触摸事件为一个时
				if (this.touchType === 0) {
					// 记录最终移动距离
					const moveX = e.changedTouches[0].clientX - this.clientX
					const moveY = e.changedTouches[0].clientY - this.clientY
					// 最终偏移距离为初始偏移距离+当前偏移距离
					this.x = this.moveX + moveX
					this.y = this.moveY + moveY
					// 当前偏移距离设置为当前位置
					this.moveX = this.x
					this.moveY = this.y
				} else if (this.touchType === 1) {
					// 当双指松开后
					console.log(e)
				}
			},
			// 因电话等打断时触发
			touchcancel (e) {
				if (this.touchType === 0) {
					this.x = 0
					this.y = 0
				} else {
					this.clientX = 0
					this.clientY = 0
					this.moveX = 0
					this.moveY = 0
					this.touchType = 0 // 0为单指触摸  1为双指
					// 初始双指距离
					this.distance = 0
					// 初始缩放比例
					this.scale = 1
				}
			},
			open () {
				this.$refs.showImage.open()
			},
			close () {
				this.x = 0
				this.src = ''
				this.y = 0
				this.clientX = 0
				this.clientY = 0
				this.moveX = 0
				this.moveY = 0
				this.touchType = 0 // 0为单指触摸  1为双指
				// 初始双指距离
				this.distance = 0
				// 初始缩放比例
				this.scale = 1
				this.$refs.showImage.close()
			}
		}
	}
</script>

<style>
	.closePopup {
		position: fixed;
		top: 40px;
		right: 40px;
		width: 50px;
		height: 50px;
		text-align: center;
		line-height: 50px;
		z-index: 99999;
	}
</style>

外面组件调用时引用或者全局注册后使用

外面图片上加个点击事件

 @click="look(url)"

方法直接调用组件open方法就OK了。

look (url) {
				this.$refs.showImg.src = url
				this.$refs.showImg.open()
			},

效果图:

---------------查看-------------------------------移动------------------------------缩放


http://www.kler.cn/news/309696.html

相关文章:

  • python中Web API 框架
  • Html css样式总结
  • 使用CUBE_MX实现STM32 DMA 功能(存储器到存储器)
  • Miracast/WifiDisplay开发相关的深入调研分析-android投屏实战开发
  • 字幕编辑用什么软件好?盘点国内外7款视频加字幕软件,简单高效!
  • [SWPU2019]Web11
  • Java文件输入输出及其常用类
  • Nginx反向代理出现502 Bad Gateway问题的解决方案
  • 如何使用 LangChain 的内置工具和工具包:深入探讨与实践指南
  • [Web安全 网络安全]-文件包含漏洞
  • 八股(8)——Spring,SpringBoot
  • 虾皮商品数据api全解析:高效获取,精准运营新利器
  • 记八月十五灵隐寺一游
  • presto/trino native 向量化 大数据计算引擎
  • MySQL之库和表操作
  • Rust 所有权 简介
  • 硬件基础知识
  • 计算机人工智能前沿进展-大语言模型方向-2024-09-13
  • [SIGGRAPH-24] CharacterGen
  • 使用c#制作一个小型桌面程序
  • 彩漩科技亮相第一届人工智能教育应用论坛,入选TOP30榜单,展示创新教育科技产品
  • Snowflake 如何通过 Apache Iceberg 和 Polaris 为大数据的未来提供动力
  • 【JavaEE初阶】多线程6(线程池\定时器)
  • C# 开发教程-入门基础
  • linux 双网卡服务器突然断电后网卡单通故障解决
  • C#通过注册表实现记住上次打开路径
  • 超级简约的B端页面,B端系统就该如此简化设计。
  • JS基础:数组for循环年龄案例
  • sql中的APPLY 和 LATERAL
  • Git 命令详解与项目迁移指南