前言
小程序单指拖拽和双指操作是一个比拟罕用的性能,成果如下图
-
实现这三个性能,次要用三个触摸事件
touchstart
、touchmove
、touchend
<view style="height: 100vh; width: 100vw"> <image src="..." style="transform: translate({{translateX}}px, {{translateY}}px) scale({{scale}}) rotate({{rotate}}deg);" catch:touchstart="touchStart" catch:touchmove="touchMove" catch:touchend="touchEnd" /> </view>
-
用了以下变量
Page({ data: { translateX: 0, // 位移 x 坐标 单位 px translateY: 0, // 位移 y 坐标 单位 px distance: 0, // 双指接触点间隔 scale: 1, // 缩放倍数 rotate: 0, // 旋转角度 oldRotate: 0, // 上一次旋转进行后的角度 startMove: { // 起始位移间隔 x: 0, y: 0, }, startTouches: [] // 起始点 touch 数组}, })
单指拖拽
- 实现单指拖拽比较简单,只须要记录挪动的点坐标,而后减去起始点坐标,就能够求出绝对页面的挪动间隔
-
touchstart
touchStart(e) { const touches = e.touches const {translateX, translateY} = this.data const {pageX, pageY} = touches[0] this.data.startMove = { x: pageX - translateX, y: pageY - translateY } this.data.startTouches = touches },
-
touchmove
touchMove(e) { const touches = e.touches const {pageX: onePageX, pageY: onePageY} = touches[0] const {startMove} = this.data this.setData({ translateX: onePageX - startMove.x, translateY: onePageY - startMove.y }) }
双指缩放
- 双指缩放的原理是依据两点坐标求出间隔 (勾股定理),而后在用挪动坐标的间隔比就能够求出缩放倍数
-
touchmove
touchMove(e) { const touches = e.touches const {pageX: onePageX, pageY: onePageY} = touches[0] const {startMove, scale, distance: oldDistance, startTouches} = this.data if (touches.length === 2 && startTouches.length === 2) { // 双指缩放 const {pageX: twoPageX, pageY: twoPageY} = touches[1] // 求出以后双指间隔 const distance = Math.sqrt((twoPageX - onePageX) ** 2 + (twoPageY - onePageY) ** 2) this.data.distance = distance this.setData({scale: scale * (distance / (oldDistance || distance)) }) } else if (startTouches.length !== 2) { // 单指拖拽 this.setData({ translateX: onePageX - startMove.x, translateY: onePageY - startMove.y }) } }
startTouches.length !== 2
这个判断的起因是避免图片跳动,因为如果你两个手指触摸,而后来到一个手指,我是禁止拖拽的,只有双指都来到后再次触摸能力单指拖拽
双指旋转
- 双指旋转的原理是依据三角函数求出起始点的角度,而后再求出挪动坐标的角度,相减而后加上上一次旋转的角度就等于你以后所需的抉择角度
touchmove
touchMove(e) {
const touches = e.touches
const {pageX: onePageX, pageY: onePageY} = touches[0]
const {startMove, scale, distance: oldDistance, startTouches, oldRotate} = this.data
if (touches.length === 2 && startTouches.length === 2) {const { pageX: twoPageX, pageY: twoPageY} = touches[1]
const distance = Math.sqrt((twoPageX - onePageX) ** 2 + (twoPageY - onePageY) ** 2)
+ let rotate = this.getAngle(touches[0], touches[1]) - this.getAngle(startTouches[0], startTouches[1]) + oldRotate
// 如果大于 360 度,就减去 360
+ rotate = rotate > 360 ? rotate - 360 : rotate
this.data.distance = distance
this.setData({scale: scale * (distance / (oldDistance || distance)),
+ rotate
})
} else if (startTouches.length !== 2) {
this.setData({
translateX: onePageX - startMove.x,
translateY: onePageY - startMove.y
})
}
},
-
getAngle
getAngle(p1, p2) { const x = p1.pageX - p2.pageX const y = p1.pageY- p2.pageY return Math.atan2(y, x) * 180 / Math.PI }
-
touchend
touchEnd() { // 保留以后旋转角度 this.data.oldRotate = this.data.rotate },
总结
- 代码片段
https://developers.weixin.qq.com/s/0nS1tImU7Rs5
- H5 原理统一,只需改一下语法即可