Feat:1.优化节点样式设置,如果设置的是连线样式不触发节点重新创建;2.优化富文本模式下同时对大量节点调用setStyle方法修改文本样式非常慢的问题
This commit is contained in:
parent
7258ed9ea7
commit
508d8fe357
@ -336,7 +336,7 @@ class MindMap {
|
|||||||
this.opt.themeConfig = config
|
this.opt.themeConfig = config
|
||||||
if (!notRender) {
|
if (!notRender) {
|
||||||
// 检查改变的是否是节点大小无关的主题属性
|
// 检查改变的是否是节点大小无关的主题属性
|
||||||
let res = checkIsNodeSizeIndependenceConfig(changedConfig)
|
const res = checkIsNodeSizeIndependenceConfig(changedConfig)
|
||||||
this.render(null, res ? '' : CONSTANTS.CHANGE_THEME)
|
this.render(null, res ? '' : CONSTANTS.CHANGE_THEME)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,7 +34,8 @@ import {
|
|||||||
formatGetNodeGeneralization,
|
formatGetNodeGeneralization,
|
||||||
sortNodeList,
|
sortNodeList,
|
||||||
throttle,
|
throttle,
|
||||||
checkClipboardReadEnable
|
checkClipboardReadEnable,
|
||||||
|
isNodeNotNeedRenderData
|
||||||
} from '../../utils'
|
} from '../../utils'
|
||||||
import { shapeList } from './node/Shape'
|
import { shapeList } from './node/Shape'
|
||||||
import { lineStyleProps } from '../../theme/default'
|
import { lineStyleProps } from '../../theme/default'
|
||||||
@ -1580,14 +1581,15 @@ class Render {
|
|||||||
|
|
||||||
// 设置节点样式
|
// 设置节点样式
|
||||||
setNodeStyle(node, prop, value) {
|
setNodeStyle(node, prop, value) {
|
||||||
let data = {
|
const data = {
|
||||||
[prop]: value
|
[prop]: value
|
||||||
}
|
}
|
||||||
// 如果开启了富文本,则需要应用到富文本上
|
// 如果开启了富文本,则需要应用到富文本上
|
||||||
if (this.hasRichTextPlugin()) {
|
if (
|
||||||
this.mindMap.richText.setNotActiveNodeStyle(node, {
|
this.hasRichTextPlugin() &&
|
||||||
[prop]: value
|
this.mindMap.richText.isHasRichTextStyle(data)
|
||||||
})
|
) {
|
||||||
|
data.resetRichText = true
|
||||||
}
|
}
|
||||||
this.setNodeDataRender(node, data)
|
this.setNodeDataRender(node, data)
|
||||||
// 更新了连线的样式
|
// 更新了连线的样式
|
||||||
@ -1598,10 +1600,13 @@ class Render {
|
|||||||
|
|
||||||
// 设置节点多个样式
|
// 设置节点多个样式
|
||||||
setNodeStyles(node, style) {
|
setNodeStyles(node, style) {
|
||||||
let data = { ...style }
|
const data = { ...style }
|
||||||
// 如果开启了富文本,则需要应用到富文本上
|
// 如果开启了富文本,则需要应用到富文本上
|
||||||
if (this.hasRichTextPlugin()) {
|
if (
|
||||||
this.mindMap.richText.setNotActiveNodeStyle(node, style)
|
this.hasRichTextPlugin() &&
|
||||||
|
this.mindMap.richText.isHasRichTextStyle(data)
|
||||||
|
) {
|
||||||
|
data.resetRichText = true
|
||||||
}
|
}
|
||||||
this.setNodeDataRender(node, data)
|
this.setNodeDataRender(node, data)
|
||||||
// 更新了连线的样式
|
// 更新了连线的样式
|
||||||
@ -1964,6 +1969,10 @@ class Render {
|
|||||||
// 设置节点数据,并判断是否渲染
|
// 设置节点数据,并判断是否渲染
|
||||||
setNodeDataRender(node, data, notRender = false) {
|
setNodeDataRender(node, data, notRender = false) {
|
||||||
this.mindMap.execCommand('SET_NODE_DATA', node, data)
|
this.mindMap.execCommand('SET_NODE_DATA', node, data)
|
||||||
|
if (isNodeNotNeedRenderData(data)) {
|
||||||
|
this.mindMap.emit('node_tree_render_end')
|
||||||
|
return
|
||||||
|
}
|
||||||
this.reRenderNodeCheckChange(node, notRender)
|
this.reRenderNodeCheckChange(node, notRender)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -57,6 +57,14 @@ class RichText {
|
|||||||
this.isCompositing = false
|
this.isCompositing = false
|
||||||
this.textNodePaddingX = 6
|
this.textNodePaddingX = 6
|
||||||
this.textNodePaddingY = 4
|
this.textNodePaddingY = 4
|
||||||
|
this.supportStyleProps = [
|
||||||
|
'fontFamily',
|
||||||
|
'fontSize',
|
||||||
|
'fontWeight',
|
||||||
|
'fontStyle',
|
||||||
|
'textDecoration',
|
||||||
|
'color'
|
||||||
|
]
|
||||||
this.initOpt()
|
this.initOpt()
|
||||||
this.extendQuill()
|
this.extendQuill()
|
||||||
this.appendCss()
|
this.appendCss()
|
||||||
@ -675,14 +683,7 @@ class RichText {
|
|||||||
// 再将样式恢复为当前主题改节点的默认样式
|
// 再将样式恢复为当前主题改节点的默认样式
|
||||||
const style = {}
|
const style = {}
|
||||||
if (this.node) {
|
if (this.node) {
|
||||||
;[
|
this.supportStyleProps.forEach(key => {
|
||||||
'fontFamily',
|
|
||||||
'fontSize',
|
|
||||||
'fontWeight',
|
|
||||||
'fontStyle',
|
|
||||||
'textDecoration',
|
|
||||||
'color'
|
|
||||||
].forEach(key => {
|
|
||||||
style[key] = this.node.style.merge(key)
|
style[key] = this.node.style.merge(key)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -713,14 +714,7 @@ class RichText {
|
|||||||
if (!this.node) return
|
if (!this.node) return
|
||||||
if (clear) {
|
if (clear) {
|
||||||
// 清除文本样式
|
// 清除文本样式
|
||||||
;[
|
this.supportStyleProps.forEach(prop => {
|
||||||
'fontFamily',
|
|
||||||
'fontSize',
|
|
||||||
'fontWeight',
|
|
||||||
'fontStyle',
|
|
||||||
'textDecoration',
|
|
||||||
'color'
|
|
||||||
].forEach(prop => {
|
|
||||||
delete this.node.nodeData.data[prop]
|
delete this.node.nodeData.data[prop]
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
@ -795,6 +789,18 @@ class RichText {
|
|||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 判断一个对象是否包含了富文本支持的样式字段
|
||||||
|
isHasRichTextStyle(obj) {
|
||||||
|
const keys = Object.keys(obj)
|
||||||
|
for (let i = 0; i < keys.length; i++) {
|
||||||
|
const key = keys[i]
|
||||||
|
if (this.supportStyleProps.includes(key)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// 给未激活的节点设置富文本样式
|
// 给未激活的节点设置富文本样式
|
||||||
setNotActiveNodeStyle(node, style) {
|
setNotActiveNodeStyle(node, style) {
|
||||||
const config = this.normalStyleToRichTextStyle(style)
|
const config = this.normalStyleToRichTextStyle(style)
|
||||||
@ -807,17 +813,9 @@ class RichText {
|
|||||||
|
|
||||||
// 检查指定节点是否存在自定义的富文本样式
|
// 检查指定节点是否存在自定义的富文本样式
|
||||||
checkNodeHasCustomRichTextStyle(node) {
|
checkNodeHasCustomRichTextStyle(node) {
|
||||||
const list = [
|
|
||||||
'fontFamily',
|
|
||||||
'fontSize',
|
|
||||||
'fontWeight',
|
|
||||||
'fontStyle',
|
|
||||||
'textDecoration',
|
|
||||||
'color'
|
|
||||||
]
|
|
||||||
const nodeData = node instanceof MindMapNode ? node.getData() : node
|
const nodeData = node instanceof MindMapNode ? node.getData() : node
|
||||||
for (let i = 0; i < list.length; i++) {
|
for (let i = 0; i < this.supportStyleProps.length; i++) {
|
||||||
if (nodeData[list[i]] !== undefined) {
|
if (nodeData[this.supportStyleProps[i]] !== undefined) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,6 +15,12 @@ export default {
|
|||||||
lineColor: '#549688',
|
lineColor: '#549688',
|
||||||
// 连线样式
|
// 连线样式
|
||||||
lineDasharray: 'none',
|
lineDasharray: 'none',
|
||||||
|
// 连线是否开启流动效果,仅在虚线时有效(需要注册LineFlow插件)
|
||||||
|
lineFlow: false,
|
||||||
|
// 流动效果一个周期的时间,单位:s
|
||||||
|
lineFlowDuration: 1,
|
||||||
|
// 流动方向是否是从父节点到子节点
|
||||||
|
lineFlowForward: true,
|
||||||
// 连线风格
|
// 连线风格
|
||||||
lineStyle: 'straight', // 曲线(curve)【仅支持logicalStructure、mindMap、verticalTimeline三种结构】、直线(straight)、直连(direct)【仅支持logicalStructure、mindMap、organizationStructure、verticalTimeline四种结构】
|
lineStyle: 'straight', // 曲线(curve)【仅支持logicalStructure、mindMap、verticalTimeline三种结构】、直线(straight)、直连(direct)【仅支持logicalStructure、mindMap、organizationStructure、verticalTimeline四种结构】
|
||||||
// 曲线连接时,根节点和其他节点的连接线样式保持统一,默认根节点为 ( 型,其他节点为 { 型,设为true后,都为 { 型。仅支持logicalStructure、mindMap两种结构
|
// 曲线连接时,根节点和其他节点的连接线样式保持统一,默认根节点为 ( 型,其他节点为 { 型,设为true后,都为 { 型。仅支持logicalStructure、mindMap两种结构
|
||||||
@ -88,8 +94,15 @@ export default {
|
|||||||
hoverRectColor: '',
|
hoverRectColor: '',
|
||||||
// 点鼠标hover和激活时显示的矩形边框的圆角大小
|
// 点鼠标hover和激活时显示的矩形边框的圆角大小
|
||||||
hoverRectRadius: 5
|
hoverRectRadius: 5
|
||||||
// paddingX: 15,
|
// 下列样式也支持给节点设置,用于覆盖最外层的设置
|
||||||
// paddingY: 5
|
// paddingX,
|
||||||
|
// paddingY,
|
||||||
|
// lineWidth,
|
||||||
|
// lineColor,
|
||||||
|
// lineDasharray,
|
||||||
|
// lineFlow,
|
||||||
|
// lineFlowDuration,
|
||||||
|
// lineFlowForward
|
||||||
},
|
},
|
||||||
// 二级节点样式
|
// 二级节点样式
|
||||||
second: {
|
second: {
|
||||||
@ -115,8 +128,6 @@ export default {
|
|||||||
lineMarkerDir: 'end',
|
lineMarkerDir: 'end',
|
||||||
hoverRectColor: '',
|
hoverRectColor: '',
|
||||||
hoverRectRadius: 5
|
hoverRectRadius: 5
|
||||||
// paddingX: 15,
|
|
||||||
// paddingY: 5
|
|
||||||
},
|
},
|
||||||
// 三级及以下节点样式
|
// 三级及以下节点样式
|
||||||
node: {
|
node: {
|
||||||
@ -142,8 +153,6 @@ export default {
|
|||||||
lineMarkerDir: 'end',
|
lineMarkerDir: 'end',
|
||||||
hoverRectColor: '',
|
hoverRectColor: '',
|
||||||
hoverRectRadius: 5
|
hoverRectRadius: 5
|
||||||
// paddingX: 15,
|
|
||||||
// paddingY: 5
|
|
||||||
},
|
},
|
||||||
// 概要节点样式
|
// 概要节点样式
|
||||||
generalization: {
|
generalization: {
|
||||||
@ -168,8 +177,6 @@ export default {
|
|||||||
endDir: [1, 0],
|
endDir: [1, 0],
|
||||||
hoverRectColor: '',
|
hoverRectColor: '',
|
||||||
hoverRectRadius: 5
|
hoverRectRadius: 5
|
||||||
// paddingX: 15,
|
|
||||||
// paddingY: 5
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,14 +204,12 @@ const nodeSizeIndependenceList = [
|
|||||||
'rootLineKeepSameInCurve',
|
'rootLineKeepSameInCurve',
|
||||||
'rootLineStartPositionKeepSameInCurve',
|
'rootLineStartPositionKeepSameInCurve',
|
||||||
'showLineMarker',
|
'showLineMarker',
|
||||||
'gradientStyle',
|
|
||||||
'lineRadius',
|
'lineRadius',
|
||||||
'startColor',
|
|
||||||
'endColor',
|
|
||||||
'startDir',
|
|
||||||
'endDir',
|
|
||||||
'hoverRectColor',
|
'hoverRectColor',
|
||||||
'hoverRectRadius'
|
'hoverRectRadius',
|
||||||
|
'lineFlow',
|
||||||
|
'lineFlowDuration',
|
||||||
|
'lineFlowForward'
|
||||||
]
|
]
|
||||||
export const checkIsNodeSizeIndependenceConfig = config => {
|
export const checkIsNodeSizeIndependenceConfig = config => {
|
||||||
let keys = Object.keys(config)
|
let keys = Object.keys(config)
|
||||||
@ -220,9 +225,13 @@ export const checkIsNodeSizeIndependenceConfig = config => {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 连线的样式
|
||||||
export const lineStyleProps = [
|
export const lineStyleProps = [
|
||||||
'lineColor',
|
'lineColor',
|
||||||
'lineDasharray',
|
'lineDasharray',
|
||||||
'lineWidth',
|
'lineWidth',
|
||||||
'lineMarkerDir'
|
'lineMarkerDir',
|
||||||
|
'lineFlow',
|
||||||
|
'lineFlowDuration',
|
||||||
|
'lineFlowForward'
|
||||||
]
|
]
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import {
|
|||||||
import MersenneTwister from './mersenneTwister'
|
import MersenneTwister from './mersenneTwister'
|
||||||
import { ForeignObject } from '@svgdotjs/svg.js'
|
import { ForeignObject } from '@svgdotjs/svg.js'
|
||||||
import merge from 'deepmerge'
|
import merge from 'deepmerge'
|
||||||
|
import { lineStyleProps } from '../theme/default'
|
||||||
|
|
||||||
// 深度优先遍历树
|
// 深度优先遍历树
|
||||||
export const walk = (
|
export const walk = (
|
||||||
@ -507,13 +508,14 @@ export const addHtmlStyle = (html, tag, style) => {
|
|||||||
if (!addHtmlStyleEl) {
|
if (!addHtmlStyleEl) {
|
||||||
addHtmlStyleEl = document.createElement('div')
|
addHtmlStyleEl = document.createElement('div')
|
||||||
}
|
}
|
||||||
|
const tags = Array.isArray(tag) ? tag : [tag]
|
||||||
addHtmlStyleEl.innerHTML = html
|
addHtmlStyleEl.innerHTML = html
|
||||||
let walk = root => {
|
let walk = root => {
|
||||||
let childNodes = root.childNodes
|
let childNodes = root.childNodes
|
||||||
childNodes.forEach(node => {
|
childNodes.forEach(node => {
|
||||||
if (node.nodeType === 1) {
|
if (node.nodeType === 1) {
|
||||||
// 元素节点
|
// 元素节点
|
||||||
if (node.tagName.toLowerCase() === tag) {
|
if (tags.includes(node.tagName.toLowerCase())) {
|
||||||
node.style.cssText = style
|
node.style.cssText = style
|
||||||
} else {
|
} else {
|
||||||
walk(node)
|
walk(node)
|
||||||
@ -790,6 +792,18 @@ export const checkIsNodeStyleDataKey = key => {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 判断一个对象是否不需要触发节点重新创建
|
||||||
|
export const isNodeNotNeedRenderData = config => {
|
||||||
|
const list = [...lineStyleProps] // 节点连线样式
|
||||||
|
const keys = Object.keys(config)
|
||||||
|
for (let i = 0; i < keys.length; i++) {
|
||||||
|
if (!list.includes(keys[i])) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// 合并图标数组
|
// 合并图标数组
|
||||||
// const data = [
|
// const data = [
|
||||||
// { type: 'priority', name: '优先级图标', list: [{ name: '1', icon: 'a' }, { name: 2, icon: 'b' }] },
|
// { type: 'priority', name: '优先级图标', list: [{ name: '1', icon: 'a' }, { name: 2, icon: 'b' }] },
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user