Vue3+Cropper.js扩展h5移动端双指旋转
新建useCropperTouch.js
// 导出一个函数,用于处理触摸事件,配合cropper.js
export function useCropperTouch(cropperRef) {// 定义是否正在触摸的变量let isTouching = false// 定义初始角度let startAngle = 0// 定义初始距离let startDistance = 0// 定义当前旋转角度let currentRotate = 0// 定义当前缩放比例let currentScale = 1// 处理触摸开始事件const handleTouchStart = (e) => {// 如果触摸点数为2且Cropper存在if (e.touches.length === 2 && cropperRef.value) {// 设置正在触摸isTouching = true// 获取两个触摸点const [touch1, touch2] = e.touches// 计算初始角度startAngle = Math.atan2(touch2.clientY - touch1.clientY, touch2.clientX - touch1.clientX)// 计算初始距离startDistance = Math.hypot(touch2.clientX - touch1.clientX, touch2.clientY - touch1.clientY)// 获取当前状态const data = cropperRef.value.getData()currentRotate = data.rotate || 0currentScale = data.scaleX || 1}}// 处理触摸移动事件const handleTouchMove = (e) => {// 如果正在触摸且触摸点数为2且Cropper存在if (isTouching && e.touches.length === 2 && cropperRef.value) {// 阻止默认事件e.preventDefault()// 获取两个触摸点const [touch1, touch2] = e.touches// 计算当前角度const currentAngle = Math.atan2(touch2.clientY - touch1.clientY,touch2.clientX - touch1.clientX)// 计算当前距离const currentDistance = Math.hypot(touch2.clientX - touch1.clientX,touch2.clientY - touch1.clientY)// 计算旋转角度变化const rotateDelta = (currentAngle - startAngle) * (180 / Math.PI)// 计算缩放比例变化const scaleDelta = currentDistance / startDistance// 直接应用到 CroppercropperRef.value.rotateTo(currentRotate + rotateDelta)cropperRef.value.scale(currentScale * scaleDelta)// 更新初始值startAngle = currentAnglestartDistance = currentDistancecurrentRotate += rotateDeltacurrentScale *= scaleDelta}}// 处理触摸结束事件const handleTouchEnd = () => {// 设置不再触摸isTouching = false}// 设置事件监听const setup = (element) => {if (!element) returnelement.addEventListener('touchstart', handleTouchStart)element.addEventListener('touchmove', handleTouchMove, { passive: false })element.addEventListener('touchend', handleTouchEnd)}// 移除事件监听const cleanup = (element) => {if (!element) returnelement.removeEventListener('touchstart', handleTouchStart)element.removeEventListener('touchmove', handleTouchMove)element.removeEventListener('touchend', handleTouchEnd)}// 在组件卸载前移除事件监听onBeforeUnmount(() => {if (cropperRef) {cleanup(cropperRef)}})// 返回设置和清理函数return { setup, cleanup }
}
使用:
import { useCropperTouch } from '@/components/useCropperTouch'const cropper = ref(null)
const { setup } = useCropperTouch(cropper)// 设置触摸事件,viewImgRef为触摸图片的ref
setup(viewImgRef.value.parentElement)