Feat:支持格式刷功能

This commit is contained in:
wanglin2
2023-08-03 16:50:07 +08:00
parent 1952280003
commit 11bb519db8
8 changed files with 167 additions and 5 deletions

View File

@@ -323,7 +323,9 @@ export const nodeDataNoStylePropList = [
'richText',
'resetRichText',
'uid',
'activeStyle'
'activeStyle',
'associativeLineTargets',
'associativeLineTargetControlOffsets'
]
// 数据缓存

View File

@@ -153,9 +153,12 @@ class Render {
// 剪切节点
this.cutNode = this.cutNode.bind(this)
this.mindMap.command.add('CUT_NODE', this.cutNode)
// 修改节点样式
// 修改节点单个样式
this.setNodeStyle = this.setNodeStyle.bind(this)
this.mindMap.command.add('SET_NODE_STYLE', this.setNodeStyle)
// 修改节点多个样式
this.setNodeStyles = this.setNodeStyles.bind(this)
this.mindMap.command.add('SET_NODE_STYLES', this.setNodeStyles)
// 切换节点是否激活
this.setNodeActive = this.setNodeActive.bind(this)
this.mindMap.command.add('SET_NODE_ACTIVE', this.setNodeActive)
@@ -859,6 +862,42 @@ class Render {
}
}
// 设置节点多个样式
setNodeStyles(node, style, isActive) {
let data = {}
if (isActive) {
data = {
activeStyle: {
...(node.nodeData.data.activeStyle || {}),
...style
}
}
} else {
data = style
}
// 如果开启了富文本,则需要应用到富文本上
if (this.mindMap.richText) {
let config = this.mindMap.richText.normalStyleToRichTextStyle(style)
if (Object.keys(config).length > 0) {
this.mindMap.richText.showEditText(node)
this.mindMap.richText.formatAllText(config)
this.mindMap.richText.hideEditText([node])
}
}
this.setNodeDataRender(node, data)
// 更新了连线的样式
let props = Object.keys(style)
let hasLineStyleProps = false
props.forEach((key) => {
if (lineStyleProps.includes(key)) {
hasLineStyleProps = true
}
})
if (hasLineStyleProps) {
;(node.parent || node).renderLine(true)
}
}
// 设置节点是否激活
setNodeActive(node, active) {
this.setNodeData(node, {

View File

@@ -43,6 +43,11 @@ function setStyle(prop, value, isActive) {
this.mindMap.execCommand('SET_NODE_STYLE', this, prop, value, isActive)
}
// 修改多个样式
function setStyles(style, isActive) {
this.mindMap.execCommand('SET_NODE_STYLES', this, style, isActive)
}
export default {
setData,
setText,
@@ -52,5 +57,6 @@ export default {
setNote,
setTag,
setShape,
setStyle
setStyle,
setStyles
}

View File

@@ -0,0 +1,76 @@
import { nodeDataNoStylePropList } from '../constants/constant'
// 格式刷插件
class Painter {
constructor({ mindMap }) {
this.mindMap = mindMap
this.isInPainter = false
this.painterNode = null
this.bindEvent()
}
bindEvent() {
this.painterOneNode = this.painterOneNode.bind(this)
this.onEndPainter = this.onEndPainter.bind(this)
this.mindMap.on('node_click', this.painterOneNode)
this.mindMap.on('draw_click', this.onEndPainter)
}
unBindEvent() {
this.mindMap.off('node_click', this.painterOneNode)
this.mindMap.off('draw_click', this.onEndPainter)
}
// 开始格式刷
startPainter() {
if (this.mindMap.opt.readonly) return
let activeNodeList = this.mindMap.renderer.activeNodeList
if (activeNodeList.length <= 0) return
this.painterNode = activeNodeList[0]
this.isInPainter = true
this.mindMap.emit('painter_start')
}
// 结束格式刷
endPainter() {
this.painterNode = null
this.isInPainter = false
}
onEndPainter() {
this.endPainter()
this.mindMap.emit('painter_end')
}
// 格式刷某个节点
painterOneNode(node) {
if (
!node ||
!this.isInPainter ||
!this.painterNode ||
!node ||
node === this.painterNode
)
return
const style = {}
const painterNodeData = this.painterNode.nodeData.data
Object.keys(painterNodeData).forEach(key => {
if (!nodeDataNoStylePropList.includes(key)) {
style[key] = painterNodeData[key]
}
})
node.setStyles(style)
if (painterNodeData.activeStyle) {
node.setStyles(painterNodeData.activeStyle, true)
}
}
// 插件被移除前做的事情
beforePluginRemove() {
this.unBindEvent()
}
}
Painter.instanceName = 'painter'
export default Painter

View File

@@ -202,6 +202,7 @@ export default {
export: 'Export',
shortcutKey: 'Shortcut key',
associativeLine: 'Associative line',
painter: 'Painter'
},
edit: {
newFeatureNoticeTitle: 'New feature reminder',

View File

@@ -202,6 +202,7 @@ export default {
export: '导出',
shortcutKey: '快捷键',
associativeLine: '关联线',
painter: '格式刷'
},
edit: {
newFeatureNoticeTitle: '新特性提醒',

View File

@@ -39,6 +39,7 @@ import AssociativeLine from 'simple-mind-map/src/plugins/AssociativeLine.js'
import TouchEvent from 'simple-mind-map/src/plugins/TouchEvent.js'
import NodeImgAdjust from 'simple-mind-map/src/plugins/NodeImgAdjust.js'
import SearchPlugin from 'simple-mind-map/src/plugins/Search.js'
import Painter from 'simple-mind-map/src/plugins/Painter.js'
import Outline from './Outline'
import Style from './Style'
import BaseStyle from './BaseStyle'
@@ -81,6 +82,7 @@ MindMap
.usePlugin(NodeImgAdjust)
.usePlugin(TouchEvent)
.usePlugin(SearchPlugin)
.usePlugin(Painter)
// 注册自定义主题
customThemeList.forEach((item) => {
@@ -153,6 +155,9 @@ export default {
this.$bus.$on('createAssociativeLine', () => {
this.mindMap.associativeLine.createLineFromActiveNode()
})
this.$bus.$on('startPainter', () => {
this.mindMap.painter.startPainter()
})
window.addEventListener('resize', () => {
this.mindMap.resize()
})
@@ -268,7 +273,9 @@ export default {
'node_tree_render_end',
'rich_text_selection_change',
'transforming-dom-to-images',
'generalization_node_contextmenu'
'generalization_node_contextmenu',
'painter_start',
'painter_end'
].forEach(event => {
this.mindMap.on(event, (...args) => {
this.$bus.$emit(event, ...args)

View File

@@ -23,6 +23,17 @@
<span class="icon iconfont iconqianjin1"></span>
<span class="text">{{ $t('toolbar.redo') }}</span>
</div>
<div
class="toolbarBtn"
:class="{
disabled: activeNodes.length <= 0 || hasGeneralization,
active: isInPainter
}"
@click="$bus.$emit('startPainter')"
>
<span class="icon iconfont iconjiedian"></span>
<span class="text">{{ $t('toolbar.painter') }}</span>
</div>
<div
class="toolbarBtn"
:class="{
@@ -195,7 +206,8 @@ export default {
forwardEnd: true,
readonly: false,
isFullDataFile: false,
timer: null
timer: null,
isInPainter: false
}
},
computed: {
@@ -227,12 +239,16 @@ export default {
this.$bus.$on('node_active', this.onNodeActive)
this.$bus.$on('back_forward', this.onBackForward)
this.$bus.$on('write_local_file', this.onWriteLocalFile)
this.$bus.$on('painter_start', this.onPainterStart)
this.$bus.$on('painter_end', this.onPainterEnd)
},
beforeDestroy() {
this.$bus.$off('mode_change', this.onModeChange)
this.$bus.$off('node_active', this.onNodeActive)
this.$bus.$off('back_forward', this.onBackForward)
this.$bus.$off('write_local_file', this.onWriteLocalFile)
this.$bus.$on('painter_start', this.onPainterStart)
this.$bus.$off('painter_end', this.onPainterEnd)
},
methods: {
...mapMutations(['setActiveSidebar']),
@@ -448,6 +464,14 @@ export default {
'你的浏览器可能不支持建议使用最新版本的Chrome浏览器'
)
}
},
onPainterStart() {
this.isInPainter = true
},
onPainterEnd() {
this.isInPainter = false
}
}
}
@@ -531,6 +555,12 @@ export default {
}
}
&.active {
.icon {
background: #f5f5f5;
}
}
&.disabled {
color: #bcbcbc;
cursor: not-allowed;