import Hammer from 'hammerjs' // 引用hammerjs // 定义缩放方法,接收一个element参数:使用export暴露该方法 export function zoomElement(el) { function point2D(x, y) { return { x: x, y: y } } // 判断 正数,负数,不是数字 function checkNumType(num) { var reg = new RegExp('^-?[0-9]*.?[0-9]*$') if (reg.test(num)) { // 用于检测一个字符串是否匹配某个模式 var absVal = Math.abs(num) // 如果参数是非负数,则返回该参数;如果参数是负数,则返回该参数的相反数。 return num == absVal ? true : false } else { console.log('this is not number') } } function exChangeNum(num, reNum) { let flag = checkNumType(num) let reFlag = checkNumType(reNum) let realNum = 0 if (!flag && reFlag) { realNum = Number('-' + reNum) } else { realNum = Number(reNum) } return realNum } var reqAnimationFrame = (function () { return ( window[Hammer.prefixed(window, 'requestAnimationFrame')] || function (callback) { window.setTimeout(callback, 1000 / 60) } ) })() var ticking = false var tMatrix = [1, 0, 0, 1, 0, 0] //x缩放,无,无,y缩放,x平移,y平移 var initScale = 1 //初始化scale el.addEventListener('touchmove', function (e) { e.preventDefault() }) var mc = new Hammer.Manager(el) var nowScale = 0 var poscenter = point2D(0, 0) // 缓存双指的中心坐标 var duration = '' // 设置过渡效果,用于双击缩放效果 var lastTranslate = point2D(0, 0) // 记录上次的偏移值 var lastcenter = point2D(el.offsetWidth / 2, el.offsetHeight / 2) // 图像的中心点,用于对比双指中心点 var center = lastcenter // 初始化为图片中心点 // 添加缩放事件 mc.add(new Hammer.Pan({ threshold: 0, pointers: 1 })) mc.add(new Hammer.Pinch({ threshold: 0 })) mc.add(new Hammer.Tap({ event: 'doubletap', taps: 2 })) mc.on('pinchstart', onPinchStart) // 双指缩放 mc.on('pinchmove', onPinch) // 双指移动 mc.on('panmove', onPan) mc.on('panstart', onPanStart) // 缩放开始 function onPinchStart(ev) { duration = '' lastTranslate = point2D(tMatrix[4], tMatrix[5]) //记录上一次的偏移值 0 0 initScale = tMatrix[0] || 1 // 手势中心点 poscenter = point2D(ev.center.x, ev.center.y) // 图像中心点 = 初始化图像中心点 + 上一次偏移量的中心点 lastcenter = point2D(center.x + lastTranslate.x, center.y + lastTranslate.y) //重新计算放大后的中心坐标 // 手势中心点 = 缩放中心点 - 图像中心点 poscenter = point2D(ev.center.x - lastcenter.x, ev.center.y - lastcenter.y) requestElementUpdate('onpinchStart') } // 缩放途中 function onPinch(ev) { // 缩放倍数 这里的缩放倍数 nowScale = initScale * ev.scale // 如果倍数小于1 则等于1 if (nowScale < 1) { nowScale = 1 } // 缩放倍数 tMatrix[0] = tMatrix[3] = nowScale let x = Number((1 - ev.scale) * poscenter.x + lastTranslate.x) let y = Number((1 - ev.scale) * poscenter.y + lastTranslate.y) let tempPosX = el.getBoundingClientRect().width / 2 - point2D(el.offsetWidth / 2, el.offsetHeight / 2).x let tempPosY = el.getBoundingClientRect().height / 2 - point2D(el.offsetWidth / 2, el.offsetHeight / 2).y if (Math.abs(x) > Math.abs(tempPosX)) { x = exChangeNum(x, tempPosX) } if (Math.abs(y) > Math.abs(tempPosY)) { y = exChangeNum(y, tempPosY) } tMatrix[4] = x tMatrix[5] = y requestElementUpdate('onpinch') } // 开始拖动 function onPanStart() { lastTranslate = point2D(tMatrix[4], tMatrix[5]) // 缓存上一次的偏移值 } // 拖动过程 function onPan(ev) { tMatrix[0] = tMatrix[3] = nowScale || initScale // 拖动的动画 1.6 duration = '1.6' let x = Number(lastTranslate.x + ev.deltaX) let y = Number(lastTranslate.y + ev.deltaY) let tempPosX = el.getBoundingClientRect().width / 2 - point2D(el.offsetWidth / 2, el.offsetHeight / 2).x let tempPosY = el.getBoundingClientRect().height / 2 - point2D(el.offsetWidth / 2, el.offsetHeight / 2).y if (Math.abs(x) > Math.abs(tempPosX)) { x = exChangeNum(x, tempPosX) } if (Math.abs(y) > Math.abs(tempPosY)) { y = exChangeNum(y, tempPosY) } tMatrix[4] = x tMatrix[5] = y requestElementUpdate('onpan') } // 每次都会·更新 因为是在移动端 所以都采用rem 否则可以直接用matrix function updateElementTransform() { el.style.transition = duration let x = tMatrix[4] + 'px' let y = tMatrix[5] + 'px' el.style.transform = 'translate(' + x + ',' + y + ') ' + 'scale(' + tMatrix[0] + ',' + tMatrix[3] + ')' el.style.WebkitTransform = 'translate(' + x + ',' + y + ') ' + 'scale(' + tMatrix[0] + ',' + tMatrix[3] + ')' el.style.msTransform = 'translate(' + x + ',' + y + ') ' + 'scale(' + tMatrix[0] + ',' + tMatrix[3] + ')' // var tmp = tMatrix.join(',') // el.style.transform = 'matrix(' + tmp + ')' // el.style.WebkitTransform = 'matrix(' + tmp + ')' // el.style.msTransform = 'matrix(' + tmp + ')' ticking = false } function requestElementUpdate() { if (!ticking) { reqAnimationFrame(updateElementTransform) ticking = true } } /** 初始化设置 */ requestElementUpdate() }