vue手势缩放组件
vue手势缩放组件原理解析关于手势缩放,最重要的点在于如何监听手势;如何获取缩放比例;如何在缩放的同时,保证双指之间的中心点一直处于原来的位置。首先,手势的监听可以使用如下方法:document.addEventListener('touchstart touchmovetouchend', function(e) {if(e.touches.length==2){//双指触摸手势事件}}缩放比例
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>
大功告成!
更多推荐
所有评论(0)