UNPKG

leo-mind-map

Version:

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

240 lines (222 loc) 6.24 kB
import { bfsWalk, throttle, checkTwoRectIsOverlap } from '../utils' import AutoMove from '../utils/AutoMove' // 节点选择插件 class Select { // 构造函数 constructor({ mindMap }) { this.mindMap = mindMap this.rect = null this.isMousedown = false this.mouseDownX = 0 this.mouseDownY = 0 this.mouseMoveX = 0 this.mouseMoveY = 0 this.isSelecting = false this.cacheActiveList = [] this.autoMove = new AutoMove(mindMap) this.bindEvent() } // 绑定事件 bindEvent() { this.onMousedown = this.onMousedown.bind(this) this.onMousemove = this.onMousemove.bind(this) this.onMouseup = this.onMouseup.bind(this) this.checkInNodes = throttle(this.checkInNodes, 300, this) this.mindMap.on('mousedown', this.onMousedown) this.mindMap.on('mousemove', this.onMousemove) this.mindMap.on('mouseup', this.onMouseup) this.mindMap.on('node_mouseup', this.onMouseup) } // 解绑事件 unBindEvent() { this.mindMap.off('mousedown', this.onMousedown) this.mindMap.off('mousemove', this.onMousemove) this.mindMap.off('mouseup', this.onMouseup) this.mindMap.off('node_mouseup', this.onMouseup) } // 鼠标按下 onMousedown(e) { const { readonly, mousedownEventPreventDefault } = this.mindMap.opt if (readonly) { return } let { useLeftKeySelectionRightKeyDrag } = this.mindMap.opt if ( !(e.ctrlKey || e.metaKey) && (useLeftKeySelectionRightKeyDrag ? e.which !== 1 : e.which !== 3) ) { return } if (mousedownEventPreventDefault) { e.preventDefault() } this.isMousedown = true this.cacheActiveList = [...this.mindMap.renderer.activeNodeList] let { x, y } = this.mindMap.toPos(e.clientX, e.clientY) this.mouseDownX = x this.mouseDownY = y this.createRect(x, y) } // 鼠标移动 onMousemove(e) { if (this.mindMap.opt.readonly) { return } if (!this.isMousedown) { return } let { x, y } = this.mindMap.toPos(e.clientX, e.clientY) this.mouseMoveX = x this.mouseMoveY = y if ( Math.abs(x - this.mouseDownX) <= 10 && Math.abs(y - this.mouseDownY) <= 10 ) { return } this.autoMove.clearAutoMoveTimer() this.autoMove.onMove( e.clientX, e.clientY, () => { this.isSelecting = true // 绘制矩形 if (this.rect) { this.rect.plot([ [this.mouseDownX, this.mouseDownY], [this.mouseMoveX, this.mouseDownY], [this.mouseMoveX, this.mouseMoveY], [this.mouseDownX, this.mouseMoveY] ]) } this.checkInNodes() }, (dir, step) => { switch (dir) { case 'left': this.mouseDownX += step break case 'top': this.mouseDownY += step break case 'right': this.mouseDownX -= step break case 'bottom': this.mouseDownY -= step break default: break } } ) } // 结束框选 onMouseup() { if (this.mindMap.opt.readonly) { return } if (!this.isMousedown) { return } this.checkTriggerNodeActiveEvent() this.autoMove.clearAutoMoveTimer() this.isMousedown = false this.cacheActiveList = [] if (this.rect) this.rect.remove() this.rect = null setTimeout(() => { this.isSelecting = false }, 0) } // 如果激活节点改变了,那么触发事件 checkTriggerNodeActiveEvent() { let isNumChange = this.cacheActiveList.length !== this.mindMap.renderer.activeNodeList.length let isNodeChange = false if (!isNumChange) { for (let i = 0; i < this.cacheActiveList.length; i++) { let cur = this.cacheActiveList[i] if ( !this.mindMap.renderer.activeNodeList.find(item => { return item.getData('uid') === cur.getData('uid') }) ) { isNodeChange = true break } } } if (isNumChange || isNodeChange) { this.mindMap.renderer.emitNodeActiveEvent() } } // 创建矩形 createRect(x, y) { if (this.rect) this.rect.remove() this.rect = this.mindMap.svg .polygon() .stroke({ color: '#0984e3' }) .fill({ color: 'rgba(9,132,227,0.3)' }) .plot([[x, y]]) } // 检测在选区里的节点 checkInNodes() { let { scaleX, scaleY, translateX, translateY } = this.mindMap.draw.transform() let minx = Math.min(this.mouseDownX, this.mouseMoveX) let miny = Math.min(this.mouseDownY, this.mouseMoveY) let maxx = Math.max(this.mouseDownX, this.mouseMoveX) let maxy = Math.max(this.mouseDownY, this.mouseMoveY) const check = node => { let { left, top, width, height } = node let right = (left + width) * scaleX + translateX let bottom = (top + height) * scaleY + translateY left = left * scaleX + translateX top = top * scaleY + translateY if ( checkTwoRectIsOverlap(minx, maxx, miny, maxy, left, right, top, bottom) ) { if (node.getData('isActive')) { return } this.mindMap.renderer.addNodeToActiveList(node) this.mindMap.renderer.emitNodeActiveEvent() } else if (node.getData('isActive')) { if (!node.getData('isActive')) { return } this.mindMap.renderer.removeNodeFromActiveList(node) this.mindMap.renderer.emitNodeActiveEvent() } } bfsWalk(this.mindMap.renderer.root, node => { check(node) // 概要节点 if (node._generalizationList && node._generalizationList.length > 0) { node._generalizationList.forEach(item => { check(item.generalizationNode) }) } }) } // 是否存在选区 hasSelectRange() { return this.isSelecting } // 插件被移除前做的事情 beforePluginRemove() { this.unBindEvent() } // 插件被卸载前做的事情 beforePluginDestroy() { this.unBindEvent() } } Select.instanceName = 'select' export default Select