import { keyMap } from './keyMap' import { CONSTANTS } from '../../constants/constant' // 快捷按键、命令处理类 export default class KeyCommand { // 构造函数 constructor(opt) { this.opt = opt this.mindMap = opt.mindMap this.shortcutMap = { //Enter: [fn] } this.shortcutMapCache = {} this.isPause = false this.isInSvg = false this.bindEvent() } // 暂停快捷键响应 pause() { this.isPause = true } // 恢复快捷键响应 recovery() { this.isPause = false } // 保存当前注册的快捷键数据,然后清空快捷键数据 save() { // 当前已经存在缓存数据了,那么直接返回 if (Object.keys(this.shortcutMapCache).length > 0) { return } this.shortcutMapCache = this.shortcutMap this.shortcutMap = {} } // 恢复保存的快捷键数据,然后清空缓存数据 restore() { // 当前不存在缓存数据,那么直接返回 if (Object.keys(this.shortcutMapCache).length <= 0) { return } this.shortcutMap = this.shortcutMapCache this.shortcutMapCache = {} } // 绑定事件 bindEvent() { this.onKeydown = this.onKeydown.bind(this) // 只有当鼠标在画布内才响应快捷键 this.mindMap.on('svg_mouseenter', () => { this.isInSvg = true }) this.mindMap.on('svg_mouseleave', () => { if (this.mindMap.renderer.textEdit.isShowTextEdit()) return if ( this.mindMap.associativeLine && this.mindMap.associativeLine.showTextEdit ) { return } this.isInSvg = false }) window.addEventListener('keydown', this.onKeydown) this.mindMap.on('beforeDestroy', () => { this.unBindEvent() }) } // 解绑事件 unBindEvent() { window.removeEventListener('keydown', this.onKeydown) } // 根据事件目标判断是否响应快捷键事件 defaultEnableCheck(e) { const target = e.target return ( target === document.body || target.classList.contains(CONSTANTS.EDIT_NODE_CLASS.SMM_NODE_EDIT_WRAP) || target.classList.contains(CONSTANTS.EDIT_NODE_CLASS.RICH_TEXT_EDIT_WRAP) || target.classList.contains(CONSTANTS.EDIT_NODE_CLASS.ASSOCIATIVE_LINE_TEXT_EDIT_WRAP) ) } // 按键事件 onKeydown(e) { const { enableShortcutOnlyWhenMouseInSvg, beforeShortcutRun, customCheckEnableShortcut } = this.mindMap.opt const checkFn = typeof customCheckEnableShortcut === 'function' ? customCheckEnableShortcut : this.defaultEnableCheck if (!checkFn(e)) return if (this.isPause || (enableShortcutOnlyWhenMouseInSvg && !this.isInSvg)) { return } Object.keys(this.shortcutMap).forEach(key => { if (this.checkKey(e, key)) { // 粘贴事件不组织,因为要监听paste事件 if (!this.checkKey(e, 'Control+v')) { e.stopPropagation() e.preventDefault() } if (typeof beforeShortcutRun === 'function') { const isStop = beforeShortcutRun(key, [ ...this.mindMap.renderer.activeNodeList ]) if (isStop) return } this.shortcutMap[key].forEach(fn => { fn() }) } }) } // 检查键值是否符合 checkKey(e, key) { let o = this.getOriginEventCodeArr(e) let k = this.getKeyCodeArr(key) if (o.length !== k.length) { return false } for (let i = 0; i < o.length; i++) { let index = k.findIndex(item => { return item === o[i] }) if (index === -1) { return false } else { k.splice(index, 1) } } return true } // 获取事件对象里的键值数组 getOriginEventCodeArr(e) { let arr = [] if (e.ctrlKey || e.metaKey) { arr.push(keyMap['Control']) } if (e.altKey) { arr.push(keyMap['Alt']) } if (e.shiftKey) { arr.push(keyMap['Shift']) } if (!arr.includes(e.keyCode)) { arr.push(e.keyCode) } return arr } // 判断是否按下了组合键 hasCombinationKey(e) { return e.ctrlKey || e.metaKey || e.altKey || e.shiftKey } // 获取快捷键对应的键值数组 getKeyCodeArr(key) { let keyArr = key.split(/\s*\+\s*/) let arr = [] keyArr.forEach(item => { arr.push(keyMap[item]) }) return arr } // 添加快捷键命令 /** * Enter * Tab | Insert * Shift + a */ addShortcut(key, fn) { key.split(/\s*\|\s*/).forEach(item => { if (this.shortcutMap[item]) { this.shortcutMap[item].push(fn) } else { this.shortcutMap[item] = [fn] } }) } // 移除快捷键命令 removeShortcut(key, fn) { key.split(/\s*\|\s*/).forEach(item => { if (this.shortcutMap[item]) { if (fn) { let index = this.shortcutMap[item].findIndex(f => { return f === fn }) if (index !== -1) { this.shortcutMap[item].splice(index, 1) } } else { this.shortcutMap[item] = [] delete this.shortcutMap[item] } } }) } // 获取指定快捷键的处理函数 getShortcutFn(key) { let res = [] key.split(/\s*\|\s*/).forEach(item => { res = this.shortcutMap[item] || [] }) return res } }