Feat:新增添加节点附加的前置和后置内容的实例化选项

This commit is contained in:
街角小林 2024-05-08 19:02:19 +08:00
parent e939b6132f
commit 706b2ee65d
4 changed files with 102 additions and 34 deletions

View File

@ -322,5 +322,9 @@ export const defaultOpt = {
// 演示插件配置
demonstrateConfig: null,
// 移动节点到画布中心、回到根节点等操作时是否将缩放层级复位为100%
resetScaleOnMoveNodeToCenter: false
resetScaleOnMoveNodeToCenter: false,
// 添加附加的节点前置内容,前置内容指和文本同一行的区域中的前置内容,不包括节点图片部分
createNodePrefixContent: null,
// 添加附加的节点后置内容,后置内容指和文本同一行的区域中的后置内容,不包括节点图片部分
createNodePostfixContent: null
}

View File

@ -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,

View File

@ -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 = `<div>${defenseXSS(this.getData('text'))}</div>`
if (!this.mindMap.commonCaches.measureRichtextNodeTextSizeEl) {
this.mindMap.commonCaches.measureRichtextNodeTextSizeEl = document.createElement('div')
this.mindMap.commonCaches.measureRichtextNodeTextSizeEl.style.position = 'fixed'
this.mindMap.commonCaches.measureRichtextNodeTextSizeEl.style.left = '-999999px'
this.mindMap.el.appendChild(this.mindMap.commonCaches.measureRichtextNodeTextSizeEl)
this.mindMap.commonCaches.measureRichtextNodeTextSizeEl =
document.createElement('div')
this.mindMap.commonCaches.measureRichtextNodeTextSizeEl.style.position =
'fixed'
this.mindMap.commonCaches.measureRichtextNodeTextSizeEl.style.left =
'-999999px'
this.mindMap.el.appendChild(
this.mindMap.commonCaches.measureRichtextNodeTextSizeEl
)
}
let div = this.mindMap.commonCaches.measureRichtextNodeTextSizeEl
div.innerHTML = html
@ -175,10 +173,11 @@ function createRichTextNode() {
height = Math.ceil(height)
g.attr('data-width', width)
g.attr('data-height', height)
let foreignObject = new ForeignObject()
foreignObject.width(width)
foreignObject.height(height)
foreignObject.add(div.children[0])
const foreignObject = createForeignObjectNode({
el: div.children[0],
width,
height
})
g.add(foreignObject)
return {
node: g,
@ -418,17 +417,21 @@ function getNoteContentPosition() {
// 测量自定义节点内容元素的宽高
function measureCustomNodeContentSize(content) {
if (!this.mindMap.commonCaches.measureCustomNodeContentSizeEl) {
this.mindMap.commonCaches.measureCustomNodeContentSizeEl = document.createElement('div')
this.mindMap.commonCaches.measureCustomNodeContentSizeEl =
document.createElement('div')
this.mindMap.commonCaches.measureCustomNodeContentSizeEl.style.cssText = `
position: fixed;
left: -99999px;
top: -99999px;
`
this.mindMap.el.appendChild(this.mindMap.commonCaches.measureCustomNodeContentSizeEl)
this.mindMap.el.appendChild(
this.mindMap.commonCaches.measureCustomNodeContentSizeEl
)
}
this.mindMap.commonCaches.measureCustomNodeContentSizeEl.innerHTML = ''
this.mindMap.commonCaches.measureCustomNodeContentSizeEl.appendChild(content)
let rect = this.mindMap.commonCaches.measureCustomNodeContentSizeEl.getBoundingClientRect()
let rect =
this.mindMap.commonCaches.measureCustomNodeContentSizeEl.getBoundingClientRect()
return {
width: rect.width,
height: rect.height

View File

@ -1342,9 +1342,7 @@ export const handleGetSvgDataExtraContent = ({
const { el, cssText, height } = res
if (el instanceof HTMLElement) {
el.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml')
const foreignObject = new ForeignObject()
foreignObject.height(height)
foreignObject.add(el)
const foreignObject = createForeignObjectNode({ el, height })
callback(foreignObject, height)
}
if (cssText) {
@ -1461,3 +1459,16 @@ export const exitFullScreen = () => {
document.mozCancelFullScreen()
}
}
// 创建foreignObject节点
export const createForeignObjectNode = ({ el, width, height }) => {
const foreignObject = new ForeignObject()
if (width !== undefined) {
foreignObject.width(width)
}
if (height !== undefined) {
foreignObject.height(height)
}
foreignObject.add(el)
return foreignObject
}