vue手势缩放组件

vue手势缩放组件

原理解析(不想看原理的朋友可以直接跳到开发步骤)

关于手势缩放,最重要的点在于如何监听手势;如何获取缩放比例;如何在缩放的同时,保证双指之间的中心点一直处于原来的位置。

首先,手势的监听可以使用如下方法:

document.addEventListener('touchstart touchmove touchend', function(e) {
    if (e.touches.length == 2) { 
	    //双指触摸手势事件  
	} 
}

缩放比例 = 开始触摸时两指间距离 / 触摸结束时两指间距离。得到缩放比例后使用transform: scale(x,y)进行缩放。

最难的是,如何保证缩放的同时,双指之间的中心点一直处于原来的位置:

假设双指之间的中心点的坐标为(x,y),则缩放k倍后,其在缩放后的坐标系中坐标为(kx, ky);

两点间的位移距离为: 水平位移sx = x – kx;  垂直位移sy = y - ky; 那么想要双指之间的中心点回到原来的位置就必须使用transform: translate(sx,sy); 平移回去。

其中,双指中心点x坐标 = (第一个手指的x坐标 - 第二个手指的x坐标)/ 2,y坐标 = (第一个手指的y坐标 - 第二个手指的y坐标)/ 2。

这里我们使用hammer.js插件,不需要自己去计算缩放比例和双指中心点,使用更简单方便。

hammer.js简介

支持的手势有:pan滑动,缩放pinch,按压press,旋转rotate,轻扫swipe,点击tap,详细属性见下官网截图:

使用方法示例:

//通过ref获取dom元素
let zoomEl = this.$refs.zoom;
//初始化hammer
var hammer = new Hammer(zoomEl);
//缩放事件默认是关闭的,需要设置启用
hammer.get('pinch').set({ enable: true });
//监听缩放事件
hammer.on("pinchmove pinchstart pinchin pinchout",e => {
    //e.type   事件类型,如pinchmove
    //e.scale  缩放比例
    //e.center 触摸点的中心
    //e.deltaX X轴偏移
    //e.deltaY Y轴偏移
});

事件对象完整属性:

好了,铺垫这么多,接下来该一步步实现缩放效果了,开发步骤如下:

一、安装hammer.js插件

npm install hammerjs --save

二、dom元素布局

<template>
	<div ref="test" class="test">
		<img src="https://whbj-yellowpage.oss-cn-shenzhen.aliyuncs.com/e_seal/template/authorization_file.png" alt="">
	</div>
</template>

三、style样式设置

<style>
	.test{
		transform-origin: 0 0;
	}
	
	.test img{
		width: 100%;
		height: 100%;
	}
</style>

四、js监听手势实现缩放

这里我们把手势操作单独封装到一个js文件当中,如:zoom.js文件。

import Hammer from 'hammerjs'//引用hammerjs

//定义缩放方法,接收一个element参数:使用export暴露该方法
export function zoomElement(el){

	var x = 0;//x轴偏移
	var y = 0;//y轴偏移
	var lastScale = 1;//上次缩放值
	var currentScale = 1;//当前缩放值
	var center;//双指中心点
	
	//初始化hammer
	var hammer = new Hammer(el);
	//缩放事件默认是关闭的,需要设置启用
	hammer.get('pinch').set({ enable: true });
	
	//监听缩放事件
	hammer.on("pinchmove pinchstart pinchin pinchout",e => {
		//缩放开始时获取上一次缩放值与双指中心点
	    if(e.type == "pinchstart"){
	        lastScale = currentScale || 1;
			center = e.center;
			console.log("centerX:"+center.x)
			console.log("centerY:"+center.y)
	    }
		//当前缩放值 = 上一次缩放值 * 缩放比例
	    currentScale = lastScale * e.scale;
		
		//如果缩放值小于1,重置为1
		if (currentScale < 1){
			currentScale = 1;
		}
		
		//偏移量 = 双指中心点 - 当前缩放值 * 双指中心点 = 双指中心点 *(1-当前缩放值)
		x = center.x * (1-currentScale)
		y = center.y * (1-currentScale)
		
		//设置transform
	    el.style.transform="translateX("+(x)+"px)"+"translateY("+(y)+"px)"+"scale(" + (currentScale)+ ")"
	});
	//监听滑动事件
	hammer.on('panright panleft panup pandown',(e)=>{
		//滑动时:偏移量 = 滑动距离 + 当前偏移量
		var translateX = e.deltaX + x
		var translateY = e.deltaY + y
		//如果偏移X值大于0:表示视图已经滑到最左侧,重置为0
		if (translateX > 0){
			translateX = 0
		}
		//如果偏移Y值大于0:表示视图已经滑到最顶部,重置为0
		if (translateY > 0){
			translateY = 0
		}
		//如果偏移X值小于(屏幕宽度-元素宽度):表示视图已经滑到最左侧,重置为0
		//屏幕宽度 = el.clientWidth
		//元素宽度 = el.getBoundingClientRect().width
		if (translateX < el.clientWidth - el.getBoundingClientRect().width){
			translateX = el.clientWidth - el.getBoundingClientRect().width
		}
		//如果偏移Y值大于(屏幕高度-元素高度):表示视图已经滑到最左侧,重置为0
		//屏幕高度 = el.clientHeight
		//元素高度 = el.getBoundingClientRect().height
		if (translateY < el.clientHeight - el.getBoundingClientRect().height){
			translateY = el.clientHeight - el.getBoundingClientRect().height
		}
		//设置transform
	    el.style.transform="translateX("+(translateX)+"px)"+"translateY("+(translateY)+"px)"+"scale(" + (currentScale)+ ")"
	});
	hammer.on('panend',(e)=>{
		//滑动结束:记录当前偏移量 
	    x = e.deltaX + x;
	    y = e.deltaY + y;
	    console.log("panendx:"+x)
	    console.log("panendy:"+y)
	})
}

五、引用zoom.js文件,传入需要缩放的组件。

<script>
	import {zoomElement} from '@/assets/static/js/zoom.js';
	
	export default {
		name: 'zoom',
		data() {
			return {
				
			};
		},
		mounted() {
			//获取需要缩放的dom元素
			let zoomEl = this.$refs.test;
			console.log("zoomEl:"+zoomEl)
			zoomElement(zoomEl)
		}
	}
	
</script>

大功告成!

 

### 实现 Vue2 中移动端手势缩放图片功能 在 Vue2 中实现移动端手势缩放图片功能,可以借助 Hammer.js 来处理多点触控事件,包括 `pinch`(捏合缩放)和 `pan`(拖动)等手势操作。Hammer.js 是一个广泛使用的手势识别库,能够有效支持触摸设备上的交互行为 [^1]。 首先,安装 Hammer.js: ```bash npm install hammerjs --save ``` 然后,在组件中使用 Hammer.js 初始化手势识别,并绑定到图片元素上: ```html <template> <div class="image-wrapper" ref="container"> <img ref="zoomableImage" :src="imageUrl" alt="Zoomable Image" class="zoomable-image" /> </div> </template> <script> import Hammer from 'hammerjs'; export default { props: ['imageUrl'], mounted() { const container = this.$refs.container; const image = this.$refs.zoomableImage; const mc = new Hammer.Manager(image); // 添加 pinch 和 pan 手势识别器 mc.add(new Hammer.Pinch()); mc.add(new Hammer.Pan()); let scale = 1; let position = { x: 0, y: 0 }; mc.on('pinch', (e) => { scale = Math.max(1, Math.min(e.scale, 3)); // 设置缩放范围为 1x 到 3x applyTransform(); }); mc.on('panstart', () => { // 开始拖动前记录当前位置 const transform = window.getComputedStyle(image).transform; if (transform && transform !== 'none') { const values = transform.match(/-?\d*\.?\d+/g); if (values && values.length >= 6) { position.x = parseFloat(values[4]); position.y = parseFloat(values[5]); } } }); mc.on('pan', (e) => { position.x += e.deltaX; position.y += e.deltaY; applyTransform(); }); const applyTransform = () => { image.style.transform = `translate(${position.x}px, ${position.y}px) scale(${scale})`; }; } }; </script> <style scoped> .image-wrapper { overflow: hidden; width: 100%; height: auto; } .zoomable-image { width: 100%; transition: transform 0.1s ease; transform-origin: center center; } </style> ``` 该代码通过 Hammer.js 的 `Pinch` 和 `Pan` 手势识别实现了对图片的缩放与平移控制。用户可以通过捏合来放大缩小图片,并通过拖动手势移动图片位置 。 此外,为了优化用户体验,可以在容器上设置 `overflow: hidden` 以防止图片超出可视区域,并通过 `transform-origin: center center` 确保缩放中心点居中显示 [^1]。 ---
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值