You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

263 lines
7.7 KiB

/* eslint-disable */
// @ts-ignore
function getLen(v) {
return Math.sqrt(v.x * v.x + v.y * v.y)
}
function dot(v1, v2) {
return v1.x * v2.x + v1.y * v2.y
}
function getAngle(v1, v2) {
var mr = getLen(v1) * getLen(v2)
if (mr === 0) return 0
var r = dot(v1, v2) / mr
if (r > 1) r = 1
return Math.acos(r)
}
function cross(v1, v2) {
return v1.x * v2.y - v2.x * v1.y
}
function getRotateAngle(v1, v2) {
var angle = getAngle(v1, v2)
if (cross(v1, v2) > 0) {
angle *= -1
}
return angle * 180 / Math.PI
}
function _swipeDirection(x1, x2, y1, y2) {
if (Math.abs(x1 - x2) >= Math.abs(y1 - y2)) {
return x1 - x2 > 0 ? 'Left' : 'Right'
} else {
return y1 - y2 > 0 ? 'Up' : 'Down'
}
}
// 实现setTimeout功能
var setTimeout = function(callback, interval, instance) {
var now = Date.now
var stime = now()
var loop = function() {
if (now() - stime >= interval) {
callback()
} else {
instance.requestAnimationFrame(loop)
}
}
instance.requestAnimationFrame(loop)
}
var start = function(event, ownerInstance) {
var instance = event.instance;
var State = instance.getState()
if(!State._init) {
State.preV = {x: null, y: null}
State.pinchStartLen = null
State.zoom = 1
State.isDoubleTap = false
State.delta = null
State.last = null
State.now = null
State.x1 = State.x2 = State.y1 = State.y2 = null
State.preTapPosition = {x: null, y: null}
// 控制定时器
State._cancelLongTap = function() {
State.longTapTimeout = false
}
State._cancelSingleTap = function() {
State.singleTapTimeout = false
}
State._tapTimeout = function() {
State.tapTimeout = false
}
State._swipeTimeout = function() {
State.swipeTimeout = false
}
State._init = true // 表示已经初始化完成
}
State.tapTimeout = true
State.singleTapTimeout = true
State.longTapTimeout = true
State.swipeTimeout = true
State.now = Date.now()
State.x1 = event.touches[0].pageX
State.y1 = event.touches[0].pageY
State.delta = State.now - (State.last || State.now)
// 触发 touchStart 事件
ownerInstance.triggerEvent('touchStart', event)
if (State.preTapPosition.x !== null) {
State.isDoubleTap = (State.delta > 0 &&
State.delta <= 250 &&
Math.abs(State.preTapPosition.x - State.x1) < 30 &&
Math.abs(State.preTapPosition.y - State.y1) < 30)
if (State.isDoubleTap) {
State._cancelSingleTap()
}
}
State.preTapPosition.x = State.x1
State.preTapPosition.y = State.y1
State.last = State.now
var preV = State.preV
var len = event.touches.length
if (len > 1) {
State._cancelLongTap()
State._cancelSingleTap()
var v = {x: event.touches[1].pageX - State.x1, y: event.touches[1].pageY - State.y1}
preV.x = v.x
preV.y = v.y
State.pinchStartLen = getLen(preV)
// 触发 multipointStart 多指点按 事件
ownerInstance.triggerEvent('multipointStart', event)
}
State._preventTap = false
setTimeout(function () {
// 触发 longTap(长按) 事件
if(State.longTapTimeout) {
ownerInstance.triggerEvent('longTap', event)
State._preventTap = true
State.longTapTimeout = true
}
}, 750, instance)
if (!instance.getDataset()['propagation']) return false
}
var move = function(event, ownerInstance) {
var instance = event.instance;
var State = instance.getState()
var preV = State.preV
var len = event.touches.length
var currentX = event.touches[0].pageX
var currentY = event.touches[0].pageY
State.isDoubleTap = false
if (len > 1) {
var sCurrentX = event.touches[1].pageX
var sCurrentY = event.touches[1].pageY
var v = {x: event.touches[1].pageX - currentX, y: event.touches[1].pageY - currentY}
if (preV.x !== null) {
if (State.pinchStartLen > 0) {
event.zoom = getLen(v) / State.pinchStartLen
// 触发 pinch 事件
ownerInstance.triggerEvent('pinch', event)
}
event.angle = getRotateAngle(v, preV)
// 触发 rotate 事件
ownerInstance.triggerEvent('rotate', event)
}
preV.x = v.x
preV.y = v.y
if (State.x2 !== null && State.sx2 !== null) {
event.deltaX = (currentX - State.x2 + sCurrentX - State.sx2) / 2
event.deltaY = (currentY - State.y2 + sCurrentY - State.sy2) / 2
} else {
event.deltaX = 0
event.deltaY = 0
}
// 触发 twoFingerPressMove 事件
ownerInstance.triggerEvent('twoFingerPressMove', event)
State.sx2 = sCurrentX
State.sy2 = sCurrentY
} else {
if (State.x2 !== null) {
event.deltaX = currentX - State.x2
event.deltaY = currentY - State.y2
// move事件中添加对当前触摸点到初始触摸点的判断,
// 如果曾经大于过某个距离(比如10),就认为是移动到某个地方又移回来,应该不再触发tap事件才对。
var movedX = Math.abs(State.x1 - State.x2)
var movedY = Math.abs(State.y1 - State.y2)
if (movedX > 10 || movedY > 10) {
State._preventTap = true
}
} else {
event.deltaX = 0
event.deltaY = 0
}
// 触发 pressMove 单指点按移动 事件
ownerInstance.triggerEvent('pressMove', event)
}
// 触发 touchMove 移动事件
ownerInstance.triggerEvent('touchMove', event)
State._cancelLongTap()
State.x2 = currentX
State.y2 = currentY
// if (len > 1) {
// // event.preventDefault()
// }
if (!instance.getDataset()['propagation']) return false
}
var end = function(event, ownerInstance) {
var instance = event.instance;
var State = instance.getState()
State._cancelLongTap()
if (event.touches.length < 2) {
// multipointEnd
ownerInstance.triggerEvent('multipointEnd', event)
State.sx2 = State.sy2 = null
}
// swipe
if ((State.x2 && Math.abs(State.x1 - State.x2) > 30) ||
(State.y2 && Math.abs(State.y1 - State.y2) > 30)) {
event.direction = _swipeDirection(State.x1, State.x2, State.y1, State.y2)
setTimeout(function () {
if(State.swipeTimeout) {
// 触发 swipe 滑动 上下左右 事件
ownerInstance.triggerEvent('swipe', event)
State.swipeTimeout = true
}
}, 0, instance)
} else {
setTimeout(function () {
if(State.tapTimeout) {
if (!State._preventTap) {
// 触发 tap 事件
ownerInstance.triggerEvent('tap', event)
}
// trigger double tap immediately
if (State.isDoubleTap) {
// 触发 doubleTap 事件
ownerInstance.triggerEvent('doubleTap', event)
State.isDoubleTap = false
}
State.tapTimeout = true
}
}, 0, instance)
if (!State.isDoubleTap) {
if (instance.getDataset()['requirefailure']) { // requireFailure
setTimeout(function () {
if(State.singleTapTimeout) {
// 触发 singleTap 事件
ownerInstance.triggerEvent('singleTap', event)
State.singleTapTimeout = true
}
}, 250, instance)
} else {
ownerInstance.triggerEvent('singleTap', event)
State.singleTapTimeout = true
}
}
}
// 触发 touchEnd 事件
ownerInstance.triggerEvent('touchEnd', event)
State.preV.x = 0
State.preV.y = 0
State.zoom = 1
State.pinchStartLen = null
State.x1 = State.x2 = null
State.y1 = State.y2 = null
if (!instance.getDataset()['propagation']) return false
}
var cancel = function(event, ownerInstance) {
var instance = event.instance;
var State = instance.getState()
State._cancelLongTap()
State._cancelSingleTap()
State._tapTimeout()
State._swipeTimeout()
// 触发 touchCancel 事件
ownerInstance.triggerEvent('touchCancel', event)
if (!instance.getDataset()['propagation']) return false
}
module.exports = {
start: start,
move: move,
end: end,
cancel: cancel
}