mirror of
https://github.com/wanglin2/mind-map.git
synced 2026-02-21 18:37:43 +08:00
162 lines
4.5 KiB
JavaScript
162 lines
4.5 KiB
JavaScript
// 手势事件支持插件
|
|
class TouchEvent {
|
|
// 构造函数
|
|
constructor({ mindMap }) {
|
|
this.mindMap = mindMap
|
|
this.touchesNum = 0
|
|
this.singleTouchstartEvent = null
|
|
this.clickNum = 0
|
|
this.touchStartScaleView = null
|
|
this.bindEvent()
|
|
}
|
|
|
|
// 绑定事件
|
|
bindEvent() {
|
|
this.onTouchstart = this.onTouchstart.bind(this)
|
|
this.onTouchmove = this.onTouchmove.bind(this)
|
|
this.onTouchcancel = this.onTouchcancel.bind(this)
|
|
this.onTouchend = this.onTouchend.bind(this)
|
|
window.addEventListener('touchstart', this.onTouchstart)
|
|
window.addEventListener('touchmove', this.onTouchmove)
|
|
window.addEventListener('touchcancel', this.onTouchcancel)
|
|
window.addEventListener('touchend', this.onTouchend)
|
|
}
|
|
|
|
// 解绑事件
|
|
unBindEvent() {
|
|
window.removeEventListener('touchstart', this.onTouchstart)
|
|
window.removeEventListener('touchmove', this.onTouchmove)
|
|
window.removeEventListener('touchcancel', this.onTouchcancel)
|
|
window.removeEventListener('touchend', this.onTouchend)
|
|
}
|
|
|
|
// 手指按下事件
|
|
onTouchstart(e) {
|
|
this.touchesNum = e.touches.length
|
|
this.touchStartScaleView = null
|
|
if (this.touchesNum === 1) {
|
|
let touch = e.touches[0]
|
|
this.singleTouchstartEvent = touch
|
|
this.dispatchMouseEvent('mousedown', touch.target, touch)
|
|
}
|
|
}
|
|
|
|
// 手指移动事件
|
|
onTouchmove(e) {
|
|
let len = e.touches.length
|
|
if (len === 1) {
|
|
let touch = e.touches[0]
|
|
this.dispatchMouseEvent('mousemove', touch.target, touch)
|
|
} else if (len === 2) {
|
|
if (this.mindMap.opt.disableTouchZoom) return
|
|
let touch1 = e.touches[0]
|
|
let touch2 = e.touches[1]
|
|
let ox = touch1.clientX - touch2.clientX
|
|
let oy = touch1.clientY - touch2.clientY
|
|
let distance = Math.sqrt(Math.pow(ox, 2) + Math.pow(oy, 2))
|
|
// 以两指中心点进行缩放
|
|
let { x: touch1ClientX, y: touch1ClientY } = this.mindMap.toPos(
|
|
touch1.clientX,
|
|
touch1.clientY
|
|
)
|
|
let { x: touch2ClientX, y: touch2ClientY } = this.mindMap.toPos(
|
|
touch2.clientX,
|
|
touch2.clientY
|
|
)
|
|
let cx = (touch1ClientX + touch2ClientX) / 2
|
|
let cy = (touch1ClientY + touch2ClientY) / 2
|
|
// 手势缩放,基于最开始的位置进行缩放(基于前一个位置缩放不是线性关系); 缩放同时支持位置拖动
|
|
const view = this.mindMap.view
|
|
if (!this.touchStartScaleView) {
|
|
this.touchStartScaleView = {
|
|
distance: distance,
|
|
scale: view.scale,
|
|
x: view.x,
|
|
y: view.y,
|
|
cx: cx,
|
|
cy: cy
|
|
}
|
|
return
|
|
}
|
|
const viewBefore = this.touchStartScaleView
|
|
let scale = viewBefore.scale * (distance / viewBefore.distance)
|
|
if (Math.abs(distance - viewBefore.distance) <= 10) {
|
|
scale = viewBefore.scale
|
|
}
|
|
const ratio = 1 - scale / viewBefore.scale
|
|
view.scale = scale < 0.1 ? 0.1 : scale
|
|
view.x =
|
|
viewBefore.x +
|
|
(cx - viewBefore.x) * ratio +
|
|
(cx - viewBefore.cx) * scale
|
|
view.y =
|
|
viewBefore.y +
|
|
(cy - viewBefore.y) * ratio +
|
|
(cy - viewBefore.cy) * scale
|
|
view.transform()
|
|
this.mindMap.emit('scale', scale)
|
|
}
|
|
}
|
|
|
|
// 手指取消事件
|
|
onTouchcancel(e) {}
|
|
|
|
// 手指松开事件
|
|
onTouchend(e) {
|
|
this.dispatchMouseEvent('mouseup', e.target)
|
|
if (this.touchesNum === 1) {
|
|
// 模拟双击事件
|
|
this.clickNum++
|
|
setTimeout(() => {
|
|
this.clickNum = 0
|
|
}, 300)
|
|
let ev = this.singleTouchstartEvent
|
|
if (this.clickNum > 1) {
|
|
this.clickNum = 0
|
|
this.dispatchMouseEvent('dblclick', ev.target, ev)
|
|
} else {
|
|
// 点击事件应该不用模拟
|
|
// this.dispatchMouseEvent('click', ev.target, ev)
|
|
}
|
|
}
|
|
this.touchesNum = 0
|
|
this.singleTouchstartEvent = null
|
|
this.touchStartScaleView = null
|
|
}
|
|
|
|
// 发送鼠标事件
|
|
dispatchMouseEvent(eventName, target, e) {
|
|
let opt = {}
|
|
if (e) {
|
|
opt = {
|
|
screenX: e.screenX,
|
|
screenY: e.screenY,
|
|
clientX: e.clientX,
|
|
clientY: e.clientY,
|
|
which: 1
|
|
}
|
|
}
|
|
let event = new MouseEvent(eventName, {
|
|
view: window,
|
|
bubbles: true,
|
|
cancelable: true,
|
|
...opt
|
|
})
|
|
target.dispatchEvent(event)
|
|
}
|
|
|
|
// 插件被移除前做的事情
|
|
beforePluginRemove() {
|
|
this.unBindEvent()
|
|
}
|
|
|
|
// 插件被卸载前做的事情
|
|
beforePluginDestroy() {
|
|
this.unBindEvent()
|
|
}
|
|
}
|
|
|
|
TouchEvent.instanceName = 'touchEvent'
|
|
|
|
export default TouchEvent
|