diff --git a/simple-mind-map/src/core/render/Render.js b/simple-mind-map/src/core/render/Render.js index db07cc55..a907b071 100644 --- a/simple-mind-map/src/core/render/Render.js +++ b/simple-mind-map/src/core/render/Render.js @@ -28,7 +28,9 @@ import { parseAddGeneralizationNodeList, checkNodeListIsEqual, createSmmFormatData, - checkSmmFormatData + checkSmmFormatData, + checkIsNodeStyleDataKey, + removeRichTextStyes } from '../../utils' import { shapeList } from './node/Shape' import { lineStyleProps } from '../../themes/default' @@ -271,6 +273,15 @@ class Render { // 定位节点 this.goTargetNode = this.goTargetNode.bind(this) this.mindMap.command.add('GO_TARGET_NODE', this.goTargetNode) + // 一键去除节点自定义样式 + this.removeCustomStyles = this.removeCustomStyles.bind(this) + this.mindMap.command.add('REMOVE_CUSTOM_STYLES', this.removeCustomStyles) + // 一键去除所有节点自定义样式 + this.removeAllNodeCustomStyles = this.removeAllNodeCustomStyles.bind(this) + this.mindMap.command.add( + 'REMOVE_ALL_NODE_CUSTOM_STYLES', + this.removeAllNodeCustomStyles + ) } // 注册快捷键 @@ -911,6 +922,65 @@ class Render { this.mindMap.render() } + // 移除节点数据的自定义样式的内部方法 + _handleRemoveCustomStyles(nodeData) { + let hasCustomStyles = false + Object.keys(nodeData).forEach(key => { + if (checkIsNodeStyleDataKey(key)) { + hasCustomStyles = true + delete nodeData[key] + } + }) + // 如果是富文本,那么还要处理富文本内容 + if (hasCustomStyles && this.mindMap.richText) { + nodeData.resetRichText = true + nodeData.text = removeRichTextStyes(nodeData.text) + } + return hasCustomStyles + } + + // 一键去除自定义样式 + removeCustomStyles(node) { + node = node || this.activeNodeList[0] + if (!node) { + return + } + const hasCustomStyles = this._handleRemoveCustomStyles(node.getData()) + if (hasCustomStyles) { + this.reRenderNodeCheckChange(node) + } + } + + // 一键去除所有节点自定义样式 + removeAllNodeCustomStyles(appointNodes) { + appointNodes = formatDataToArray(appointNodes) + let hasCustomStyles = false + // 指定了节点列表,那么遍历该节点列表 + if (appointNodes.length > 0) { + appointNodes.forEach(node => { + const _hasCustomStyles = this._handleRemoveCustomStyles(node.getData()) + if (_hasCustomStyles) hasCustomStyles = true + }) + } else { + // 否则遍历整棵树 + walk(this.renderTree, null, node => { + const _hasCustomStyles = this._handleRemoveCustomStyles(node.data) + if (_hasCustomStyles) hasCustomStyles = true + // 不要忘记概要节点 + if (node.data.generalization && node.data.generalization.length > 0) { + node.data.generalization.forEach(generalizationData => { + const _hasCustomStyles = + this._handleRemoveCustomStyles(generalizationData) + if (_hasCustomStyles) hasCustomStyles = true + }) + } + }) + } + if (hasCustomStyles) { + this.mindMap.reRender() + } + } + // 复制节点 copy() { this.beingCopyData = this.copyNode() @@ -1649,6 +1719,11 @@ class Render { // 设置节点数据,并判断是否渲染 setNodeDataRender(node, data, notRender = false) { this.mindMap.execCommand('SET_NODE_DATA', node, data) + this.reRenderNodeCheckChange(node, notRender) + } + + // 重新节点某个节点,判断节点大小是否发生了改变,是的话触发重绘 + reRenderNodeCheckChange(node, notRender) { let changed = node.reRender() if (changed) { if (!notRender) this.mindMap.render() diff --git a/simple-mind-map/src/utils/index.js b/simple-mind-map/src/utils/index.js index c6786844..3afa5812 100644 --- a/simple-mind-map/src/utils/index.js +++ b/simple-mind-map/src/utils/index.js @@ -688,6 +688,52 @@ export const textToNodeRichTextWithWrap = html => { .join('') } +// 去除富文本内容的样式,包括样式标签,比如strong、em、s等 +// 但要保留数学公式内容 +let removeRichTextStyesEl = null +export const removeRichTextStyes = html => { + if (!removeRichTextStyesEl) { + removeRichTextStyesEl = document.createElement('div') + } + removeRichTextStyesEl.innerHTML = html + // 首先用占位文本替换掉所有的公式 + const formulaList = removeRichTextStyesEl.querySelectorAll('.ql-formula') + Array.from(formulaList).forEach(el => { + const placeholder = document.createTextNode('$smmformula$') + el.parentNode.replaceChild(placeholder, el) + }) + // 然后遍历每行节点,去掉内部的所有标签,转为文本 + const childNodes = removeRichTextStyesEl.childNodes + let list = [] + for (let i = 0; i < childNodes.length; i++) { + const node = childNodes[i] + if (node.nodeType === 1) { + // 元素节点 + list.push(node.textContent) + } else if (node.nodeType === 3) { + // 文本节点 + list.push(node.nodeValue) + } + } + // 拼接文本 + html = list + .map(item => { + return `
${htmlEscape(item)}
` + }) + .join('') + // 将公式添加回去 + if (formulaList.length > 0) { + html = html.replace(/\$smmformula\$/g, '') + removeRichTextStyesEl.innerHTML = html + const els = removeRichTextStyesEl.querySelectorAll('.smmformula') + Array.from(els).forEach((el, index) => { + el.parentNode.replaceChild(formulaList[index], el) + }) + html = removeRichTextStyesEl.innerHTML + } + return html +} + // 判断是否是移动端环境 export const isMobile = () => { return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(