diff --git a/simple-mind-map/src/constants/defaultOptions.js b/simple-mind-map/src/constants/defaultOptions.js index d49a52aa..ee9417ce 100644 --- a/simple-mind-map/src/constants/defaultOptions.js +++ b/simple-mind-map/src/constants/defaultOptions.js @@ -322,5 +322,9 @@ export const defaultOpt = { // 演示插件配置 demonstrateConfig: null, // 移动节点到画布中心、回到根节点等操作时是否将缩放层级复位为100% - resetScaleOnMoveNodeToCenter: false + resetScaleOnMoveNodeToCenter: false, + // 添加附加的节点前置内容,前置内容指和文本同一行的区域中的前置内容,不包括节点图片部分 + createNodePrefixContent: null, + // 添加附加的节点后置内容,后置内容指和文本同一行的区域中的后置内容,不包括节点图片部分 + createNodePostfixContent: null } diff --git a/simple-mind-map/src/core/render/node/Node.js b/simple-mind-map/src/core/render/node/Node.js index 075ccb4b..ff471177 100644 --- a/simple-mind-map/src/core/render/node/Node.js +++ b/simple-mind-map/src/core/render/node/Node.js @@ -1,6 +1,6 @@ import Style from './Style' import Shape from './Shape' -import { G, ForeignObject, Rect } from '@svgdotjs/svg.js' +import { G, Rect } from '@svgdotjs/svg.js' import nodeGeneralizationMethods from './nodeGeneralization' import nodeExpandBtnMethods from './nodeExpandBtn' import nodeCommandWrapsMethods from './nodeCommandWraps' @@ -8,7 +8,7 @@ import nodeCreateContentsMethods from './nodeCreateContents' import nodeExpandBtnPlaceholderRectMethods from './nodeExpandBtnPlaceholderRect' import nodeCooperateMethods from './nodeCooperate' import { CONSTANTS } from '../../../constants/constant' -import { copyNodeTree } from '../../../utils/index' +import { copyNodeTree, createForeignObjectNode } from '../../../utils/index' // 节点类 class Node { @@ -76,6 +76,8 @@ class Node { this.noteEl = null this.noteContentIsShow = false this._attachmentData = null + this._prefixData = null + this._postfixData = null this._expandBtn = null this._lastExpandBtnType = null this._showExpandBtn = false @@ -182,7 +184,12 @@ class Node { // 创建节点的各个内容对象数据 createNodeData() { // 自定义节点内容 - let { isUseCustomNodeContent, customCreateNodeContent } = this.mindMap.opt + let { + isUseCustomNodeContent, + customCreateNodeContent, + createNodePrefixContent, + createNodePostfixContent + } = this.mindMap.opt if (isUseCustomNodeContent && customCreateNodeContent) { this._customNodeContent = customCreateNodeContent(this) } @@ -201,6 +208,12 @@ class Node { this._tagData = this.createTagNode() this._noteData = this.createNoteNode() this._attachmentData = this.createAttachmentNode() + this._prefixData = createNodePrefixContent + ? createNodePrefixContent(this) + : null + this._postfixData = createNodePostfixContent + ? createNodePostfixContent(this) + : null } // 计算节点的宽高 @@ -237,6 +250,11 @@ class Node { this._rectInfo.imgContentWidth = imgContentWidth = this._imgData.width this._rectInfo.imgContentHeight = imgContentHeight = this._imgData.height } + // 自定义前置内容 + if (this._prefixData) { + textContentWidth += this._prefixData.width + textContentHeight = Math.max(textContentHeight, this._prefixData.height) + } // 图标 if (this._iconData.length > 0) { textContentWidth += this._iconData.reduce((sum, cur) => { @@ -277,6 +295,11 @@ class Node { this._attachmentData.height ) } + // 自定义后置内容 + if (this._postfixData) { + textContentWidth += this._postfixData.width + textContentHeight = Math.max(textContentHeight, this._postfixData.height) + } // 文字内容部分的尺寸 this._rectInfo.textContentWidth = textContentWidth this._rectInfo.textContentHeight = textContentHeight @@ -337,10 +360,11 @@ class Node { } // 如果存在自定义节点内容,那么使用自定义节点内容 if (this.isUseCustomNodeContent()) { - let foreignObject = new ForeignObject() - foreignObject.width(width) - foreignObject.height(height) - foreignObject.add(this._customNodeContent) + const foreignObject = createForeignObjectNode({ + el: this._customNodeContent, + width, + height + }) this.group.add(foreignObject) addHoverNode() return @@ -355,6 +379,19 @@ class Node { // 内容节点 let textContentNested = new G() let textContentOffsetX = 0 + // 自定义前置内容 + if (this._prefixData) { + const foreignObject = createForeignObjectNode({ + el: this._prefixData.el, + width: this._prefixData.width, + height: this._prefixData.height + }) + foreignObject + .x(textContentOffsetX) + .y((this._rectInfo.textContentHeight - this._prefixData.height) / 2) + textContentNested.add(foreignObject) + textContentOffsetX += this._prefixData.width + textContentItemMargin + } // icon let iconNested = new G() if (this._iconData && this._iconData.length > 0) { @@ -375,7 +412,7 @@ class Node { this._textData.node.attr('data-offsetx', textContentOffsetX) // 修复safari浏览器节点存在图标时文字位置不正确的问题 ;(this._textData.nodeContent || this._textData.node) - .x(-oldX)// 修复非富文本模式下同时存在图标和换行的文本时,被收起和展开时图标与文字距离会逐渐拉大的问题 + .x(-oldX) // 修复非富文本模式下同时存在图标和换行的文本时,被收起和展开时图标与文字距离会逐渐拉大的问题 .x(textContentOffsetX) .y(0) textContentNested.add(this._textData.node) @@ -419,6 +456,19 @@ class Node { textContentNested.add(this._attachmentData.node) textContentOffsetX += this._attachmentData.width } + // 自定义后置内容 + if (this._postfixData) { + const foreignObject = createForeignObjectNode({ + el: this._postfixData.el, + width: this._postfixData.width, + height: this._postfixData.height + }) + foreignObject + .x(textContentOffsetX) + .y((this._rectInfo.textContentHeight - this._postfixData.height) / 2) + textContentNested.add(foreignObject) + textContentOffsetX += this._postfixData.width + } // 文字内容整体 textContentNested.translate( width / 2 - textContentNested.bbox().width / 2, diff --git a/simple-mind-map/src/core/render/node/nodeCreateContents.js b/simple-mind-map/src/core/render/node/nodeCreateContents.js index 9c09afeb..984b0fbf 100644 --- a/simple-mind-map/src/core/render/node/nodeCreateContents.js +++ b/simple-mind-map/src/core/render/node/nodeCreateContents.js @@ -4,20 +4,13 @@ import { removeHtmlStyle, addHtmlStyle, checkIsRichText, - isUndef + isUndef, + createForeignObjectNode } from '../../../utils' -import { - Image as SVGImage, - SVG, - A, - G, - Rect, - Text, - ForeignObject -} from '@svgdotjs/svg.js' +import { Image as SVGImage, SVG, A, G, Rect, Text } from '@svgdotjs/svg.js' import iconsSvg from '../../../svg/icons' import { CONSTANTS } from '../../../constants/constant' -import {defenseXSS} from "../../../utils/xss"; +import { defenseXSS } from '../../../utils/xss' // 创建图片节点 function createImgNode() { @@ -151,10 +144,15 @@ function createRichTextNode() { } let html = `