UNPKG

leo-mind-map

Version:

一个简单的web在线思维导图

194 lines (181 loc) 5.72 kB
import { getTwoPointDistance } from '../utils' // 手势事件支持插件 class TouchEvent { // 构造函数 constructor({ mindMap }) { this.mindMap = mindMap this.touchesNum = 0 this.singleTouchstartEvent = null this.clickNum = 0 this.touchStartScaleView = null this.lastTouchStartPosition = null this.lastTouchStartDistance = 0 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, { passive: false }) window.addEventListener('touchmove', this.onTouchmove, { passive: false }) window.addEventListener('touchcancel', this.onTouchcancel, { passive: false }) window.addEventListener('touchend', this.onTouchend, { passive: false }) } // 解绑事件 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] if (this.lastTouchStartPosition) { this.lastTouchStartDistance = getTwoPointDistance( this.lastTouchStartPosition.x, this.lastTouchStartPosition.y, touch.clientX, touch.clientY ) } this.lastTouchStartPosition = { x: touch.clientX, y: touch.clientY } 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) { let { disableTouchZoom, minTouchZoomScale, maxTouchZoomScale } = this.mindMap.opt if (disableTouchZoom) return minTouchZoomScale = minTouchZoomScale === -1 ? -Infinity : minTouchZoomScale / 100 maxTouchZoomScale = maxTouchZoomScale === -1 ? Infinity : maxTouchZoomScale / 100 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 } scale = scale < minTouchZoomScale ? minTouchZoomScale : scale > maxTouchZoomScale ? maxTouchZoomScale : scale const ratio = 1 - scale / viewBefore.scale view.scale = 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 this.lastTouchStartPosition = null this.lastTouchStartDistance = 0 }, 300) let ev = this.singleTouchstartEvent if (this.clickNum > 1 && this.lastTouchStartDistance <= 5) { 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: document.defaultView, bubbles: true, cancelable: true, ...opt }) target.dispatchEvent(event) } // 插件被移除前做的事情 beforePluginRemove() { this.unBindEvent() } // 插件被卸载前做的事情 beforePluginDestroy() { this.unBindEvent() } } TouchEvent.instanceName = 'touchEvent' export default TouchEvent