diff --git a/simple-mind-map/src/constants/defaultOptions.js b/simple-mind-map/src/constants/defaultOptions.js index 0430b531..298343fb 100644 --- a/simple-mind-map/src/constants/defaultOptions.js +++ b/simple-mind-map/src/constants/defaultOptions.js @@ -224,5 +224,10 @@ export const defaultOpt = { // 多少时间内只允许添加一次历史记录,避免添加没有必要的中间状态,单位:ms addHistoryTime: 100, // 是否禁止拖动画布 - isDisableDrag: false + isDisableDrag: false, + // 鼠标移入概要高亮所属节点时的高亮框样式 + highlightNodeBoxStyle: { + stroke: 'rgb(94, 200, 248)', + fill: 'transparent' + } } diff --git a/simple-mind-map/src/core/render/Render.js b/simple-mind-map/src/core/render/Render.js index 30f5b20d..31b2761c 100644 --- a/simple-mind-map/src/core/render/Render.js +++ b/simple-mind-map/src/core/render/Render.js @@ -30,6 +30,7 @@ import { import { shapeList } from './node/Shape' import { lineStyleProps } from '../../themes/default' import { CONSTANTS, ERROR_TYPES } from '../../constants/constant' +import { Polygon } from '@svgdotjs/svg.js' // 布局列表 const layouts = { @@ -84,6 +85,8 @@ class Render { this.beingPasteText = '' this.beingPasteImgSize = 0 this.currentBeingPasteType = '' + // 节点高亮框 + this.highlightBoxNode = null // 布局 this.setLayout() // 绑定事件 @@ -1065,6 +1068,7 @@ class Render { this.mindMap.execCommand('SET_NODE_DATA', targetNode, { generalization }) + this.closeHighlightNode() } // 仅删除当前节点 @@ -1408,7 +1412,9 @@ class Render { } const nodeList = this.activeNodeList.filter(node => { return ( - !node.isRoot && !node.isGeneralization && !node.checkHasSelfGeneralization() + !node.isRoot && + !node.isGeneralization && + !node.checkHasSelfGeneralization() ) }) const list = parseAddGeneralizationNodeList(nodeList) @@ -1458,6 +1464,7 @@ class Render { }) }) this.mindMap.render() + this.closeHighlightNode() } // 设置节点自定义位置 @@ -1599,6 +1606,60 @@ class Render { emitNodeActiveEvent() { this.mindMap.emit('node_active', null, [...this.activeNodeList]) } + + // 高亮节点或子节点 + highlightNode(node, range) { + const { highlightNodeBoxStyle = {} } = this.mindMap.opt + if (!this.highlightBoxNode) { + this.highlightBoxNode = new Polygon() + .stroke({ + color: highlightNodeBoxStyle.stroke || 'transparent' + }) + .fill({ + color: highlightNodeBoxStyle.fill || 'transparent' + }) + } + let minx = Infinity, + miny = Infinity, + maxx = -Infinity, + maxy = -Infinity + if (range) { + const children = node.children.slice(range[0], range[1] + 1) + children.forEach(child => { + if (child.left < minx) { + minx = child.left + } + if (child.top < miny) { + miny = child.top + } + const right = child.left + child.width + const bottom = child.top + child.height + if (right > maxx) { + maxx = right + } + if (bottom > maxy) { + maxy = bottom + } + }) + } else { + minx = node.left + miny = node.top + maxx = node.left + node.width + maxy = node.top + node.height + } + this.highlightBoxNode.plot([ + [minx, miny], + [maxx, miny], + [maxx, maxy], + [minx, maxy] + ]) + this.mindMap.otherDraw.add(this.highlightBoxNode) + } + + // 关闭高亮 + closeHighlightNode() { + this.highlightBoxNode.remove() + } } export default Render diff --git a/simple-mind-map/src/core/render/node/Node.js b/simple-mind-map/src/core/render/node/Node.js index 4421546d..0d718a22 100644 --- a/simple-mind-map/src/core/render/node/Node.js +++ b/simple-mind-map/src/core/render/node/Node.js @@ -458,12 +458,18 @@ class Node { this._isMouseenter = true // 显示展开收起按钮 this.showExpandBtn() + if (this.isGeneralization) { + this.handleGeneralizationMouseenter() + } this.mindMap.emit('node_mouseenter', this, e) }) this.group.on('mouseleave', e => { if (!this._isMouseenter) return this._isMouseenter = false this.hideExpandBtn() + if (this.isGeneralization) { + this.handleGeneralizationMouseleave() + } this.mindMap.emit('node_mouseleave', this, e) }) // 双击事件 @@ -1002,10 +1008,29 @@ class Node { return this.style.hasCustomStyle() } - // 获取节点的尺寸和位置信息,位置信息相对于页面 + // 获取节点的尺寸和位置信息,宽高是应用了缩放效果后的实际宽高,位置是相对于浏览器窗口左上角的位置 getRect() { return this.group.rbox() } + + // 获取节点的尺寸和位置信息,宽高是应用了缩放效果后的实际宽高,位置信息相对于画布 + getRectInSvg() { + let { scaleX, scaleY, translateX, translateY } = + this.mindMap.draw.transform() + let { left, top, width, height } = this + let right = (left + width) * scaleX + translateX + let bottom = (top + height) * scaleY + translateY + left = left * scaleX + translateX + top = top * scaleY + translateY + return { + left, + right, + top, + bottom, + width: width * scaleX, + height: height * scaleY + } + } } export default Node diff --git a/simple-mind-map/src/core/render/node/nodeGeneralization.js b/simple-mind-map/src/core/render/node/nodeGeneralization.js index cfbd042b..eb6dbb6e 100644 --- a/simple-mind-map/src/core/render/node/nodeGeneralization.js +++ b/simple-mind-map/src/core/render/node/nodeGeneralization.js @@ -177,6 +177,29 @@ function setGeneralizationOpacity(val) { }) } +// 处理概要节点鼠标移入事件 +function handleGeneralizationMouseenter() { + const belongNode = this.generalizationBelongNode + const list = belongNode.formatGetGeneralization() + const index = belongNode.getGeneralizationNodeIndex(this) + const generalizationData = list[index] + // 区间概要,框子节点 + if ( + Array.isArray(generalizationData.range) && + generalizationData.range.length > 0 + ) { + this.mindMap.renderer.highlightNode(belongNode, generalizationData.range) + } else { + // 否则框自己 + this.mindMap.renderer.highlightNode(belongNode) + } +} + +// 处理概要节点鼠标移出事件 +function handleGeneralizationMouseleave() { + this.mindMap.renderer.closeHighlightNode() +} + export default { formatGetGeneralization, checkHasGeneralization, @@ -189,5 +212,7 @@ export default { removeGeneralization, hideGeneralization, showGeneralization, - setGeneralizationOpacity + setGeneralizationOpacity, + handleGeneralizationMouseenter, + handleGeneralizationMouseleave } diff --git a/simple-mind-map/src/utils/xmind.js b/simple-mind-map/src/utils/xmind.js index 373bd7da..43948d02 100644 --- a/simple-mind-map/src/utils/xmind.js +++ b/simple-mind-map/src/utils/xmind.js @@ -154,15 +154,12 @@ export const handleNodeImageToXmind = async ( try { let imgName = '' let imgData = node.data.image - console.log(1, imgData) // base64之外的其他图片要先转换成data:url if (!/^data:/.test(node.data.image)) { imgData = await imgToDataUrl(node.data.image) - console.log(2, imgData) } // 从data:url中解析出图片类型和ase64 let dataUrlRes = parseDataUrl(imgData) - console.log(3, dataUrlRes) imgName = 'image_' + imageList.length + '.' + dataUrlRes.type imageList.push({ name: imgName, diff --git a/web/src/pages/Edit/components/Edit.vue b/web/src/pages/Edit/components/Edit.vue index 215ae601..4715557d 100644 --- a/web/src/pages/Edit/components/Edit.vue +++ b/web/src/pages/Edit/components/Edit.vue @@ -408,6 +408,11 @@ export default { // console.log('销毁') // this.mindMap.destroy() // }, 10000) + // 测试 + // setTimeout(() => { + // console.log(this.mindMap.renderer.root.getRect()) + // console.log(this.mindMap.renderer.root.getRectInSvg()) + // }, 5000); }, // url中是否存在要打开的文件