Skip to content

Commit

Permalink
Merge branch 'feature' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
wanglin2 committed Sep 11, 2024
2 parents 14ebd7a + ac13aa8 commit 075bf54
Show file tree
Hide file tree
Showing 40 changed files with 890 additions and 273 deletions.
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ Github:[releases](https://github.com/wanglin2/mind-map/releases)。百度云

官方提供了如下插件,可根据需求按需引入(某个功能不生效大概率是因为你没有引入对应的插件),具体使用方式请查看文档:

> RichText(节点富文本插件)、Select(鼠标多选节点插件)、Drag(节点拖拽插件)、AssociativeLine(关联线插件)、Export(导出插件)、KeyboardNavigation(键盘导航插件)、MiniMap(小地图插件)、Watermark(水印插件)、TouchEvent(移动端触摸事件支持插件)、NodeImgAdjust(拖拽调整节点图片大小插件)、Search(搜索插件)、Painter(节点格式刷插件)、Scrollbar(滚动条插件)、Formula(数学公式插件)、Cooperate(协同编辑插件)、RainbowLines(彩虹线条插件)、Demonstrate(演示模式插件)、OuterFrame(外框插件)、HandDrawnLikeStyle(手绘风格插件)[收费]、Notation(节点标记插件)[收费]、Numbers(节点编号插件)[收费]
> RichText(节点富文本插件)、Select(鼠标多选节点插件)、Drag(节点拖拽插件)、AssociativeLine(关联线插件)、Export(导出插件)、KeyboardNavigation(键盘导航插件)、MiniMap(小地图插件)、Watermark(水印插件)、TouchEvent(移动端触摸事件支持插件)、NodeImgAdjust(拖拽调整节点图片大小插件)、Search(搜索插件)、Painter(节点格式刷插件)、Scrollbar(滚动条插件)、Formula(数学公式插件)、Cooperate(协同编辑插件)、RainbowLines(彩虹线条插件)、Demonstrate(演示模式插件)、OuterFrame(外框插件)、HandDrawnLikeStyle(手绘风格插件)[收费]、Notation(节点标记插件)[收费]、Numbers(节点编号插件)[收费]、Freemind(Freemind格式导入导出插件)[收费]、Excel(Excel格式导入导出插件)[收费]
本项目不会实现的特性:

Expand Down Expand Up @@ -457,4 +457,16 @@ const mindMap = new MindMap({
<img src="./web/src/assets/avatar/炫.jpg" style="width: 50px;height: 50px;" />
<span>炫</span>
</span>
<span>
<img src="./web/src/assets/avatar/Lawliet.jpg" style="width: 50px;height: 50px;" />
<span>Lawliet</span>
</span>
<span>
<img src="./web/src/assets/avatar/一叶孤舟.jpg" style="width: 50px;height: 50px;" />
<span>一叶孤舟</span>
</span>
<span>
<img src="./web/src/assets/avatar/default.png" style="width: 50px;height: 50px;" />
<span>晏江</span>
</span>
</p>
2 changes: 1 addition & 1 deletion copy.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ if (fs.existsSync(src)) {
fs.unlinkSync(src)
}

console.warn('请检查手绘风格、标记插件、编号插件是否启用!!!')
console.warn('请检查付费插件是否启用!!!')
2 changes: 1 addition & 1 deletion simple-mind-map/full.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ MindMap.iconList = icons.nodeIconList
MindMap.constants = constants
MindMap.themes = themes
MindMap.defaultTheme = defaultTheme
MindMap.version = '0.11.0'
MindMap.version = '0.11.1'

MindMap.usePlugin(MiniMap)
.usePlugin(Watermark)
Expand Down
2 changes: 1 addition & 1 deletion simple-mind-map/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "simple-mind-map",
"version": "0.11.0",
"version": "0.11.1",
"description": "一个简单的web在线思维导图",
"authors": [
{
Expand Down
4 changes: 3 additions & 1 deletion simple-mind-map/src/constants/constant.js
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,9 @@ export const nodeDataNoStylePropList = [
'notation',
'outerFrame',
'number',
'range'
'range',
'customLeft',
'customTop'
]

// 错误类型
Expand Down
23 changes: 14 additions & 9 deletions simple-mind-map/src/constants/defaultOptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,7 @@ export const defaultOpt = {
close: ''
},
// 处理收起节点数量
expandBtnNumHandler: num => {
return num
},
expandBtnNumHandler: null,
// 是否显示带数量的收起按钮
isShowExpandNum: true,
// 是否只有当鼠标在画布内才响应快捷键事件
Expand Down Expand Up @@ -176,11 +174,6 @@ export const defaultOpt = {
addHistoryTime: 100,
// 是否禁止拖动画布
isDisableDrag: false,
// 鼠标移入概要高亮所属节点时的高亮框样式
highlightNodeBoxStyle: {
stroke: 'rgb(94, 200, 248)',
fill: 'transparent'
},
// 创建新节点时的行为
/*
DEFAULT :默认会激活新创建的节点,并且进入编辑模式。如果同时创建了多个新节点,那么只会激活而不会进入编辑模式
Expand Down Expand Up @@ -238,6 +231,10 @@ export const defaultOpt = {
padding: 100, // 超出画布四周指定范围内依旧渲染节点
removeNodeWhenOutCanvas: true // 节点移除画布可视区域后从画布删除
},
// 如果节点文本为空,那么为了避免空白节点高度塌陷,会用该字段指定的文本测量一个高度
emptyTextMeasureHeightText: 'abc123我和你',
// 是否在进行节点文本编辑时实时更新节点大小和节点位置,开启后当节点数量比较多时可能会造成卡顿
openRealtimeRenderOnNodeTextEdit: false,

// 【Select插件】
// 多选节点时鼠标移动到边缘时的画布移动偏移量
Expand Down Expand Up @@ -409,5 +406,13 @@ export const defaultOpt = {

// 【OuterFrame】插件
outerFramePaddingX: 10,
outerFramePaddingY: 10
outerFramePaddingY: 10,

// 【Painter】插件
// 是否只格式刷节点手动设置的样式,不考虑节点通过主题的应用的样式
onlyPainterNodeCustomStyles: false,

// 【NodeImgAdjust】插件
// 拦截节点图片的删除,点击节点图片上的删除按钮删除图片前会调用该函数,如果函数返回true则取消删除
beforeDeleteNodeImg: null
}
111 changes: 79 additions & 32 deletions simple-mind-map/src/core/render/Render.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ class Render {
this.currentBeingPasteType = ''
// 节点高亮框
this.highlightBoxNode = null
this.highlightBoxNodeStyle = null
// 上一次节点激活数据
this.lastActiveNode = null
this.lastActiveNodeList = []
Expand Down Expand Up @@ -147,6 +148,19 @@ class Render {
})
// 性能模式
this.performanceMode()
// 实时渲染当节点文本编辑时
if (this.mindMap.opt.openRealtimeRenderOnNodeTextEdit) {
this.mindMap.on('node_text_edit_change', ({ node, text }) => {
node._textData = node.createTextNode(text)
const { width, height } = node.getNodeRect()
node.width = width
node.height = height
node.layout()
this.mindMap.render(() => {
this.textEdit.updateTextEditNode()
})
})
}
}

// 性能模式,懒加载节点
Expand Down Expand Up @@ -1593,40 +1607,53 @@ class Render {
}

// 展开所有
expandAllNode() {
expandAllNode(uid = '') {
if (!this.renderTree) return
walk(
this.renderTree,
null,
node => {
if (!node.data.expand) {
node.data.expand = true
}
},
null,
true,
0,
0
)

const _walk = (node, enableExpand) => {
// 如果该节点为目标节点,那么修改允许展开的标志
if (!enableExpand && node.data.uid === uid) {
enableExpand = true
}
if (enableExpand && !node.data.expand) {
node.data.expand = true
}
if (node.children && node.children.length > 0) {
node.children.forEach(child => {
_walk(child, enableExpand)
})
}
}
_walk(this.renderTree, !uid)

this.mindMap.render()
}

// 收起所有
unexpandAllNode(isSetRootNodeCenter = true) {
unexpandAllNode(isSetRootNodeCenter = true, uid = '') {
if (!this.renderTree) return
walk(
this.renderTree,
null,
(node, parent, isRoot) => {
if (!isRoot && node.children && node.children.length > 0) {
node.data.expand = false
}
},
null,
true,
0,
0
)

const _walk = (node, isRoot, enableUnExpand) => {
// 如果该节点为目标节点,那么修改允许展开的标志
if (!enableUnExpand && node.data.uid === uid) {
enableUnExpand = true
}
if (
enableUnExpand &&
!isRoot &&
node.children &&
node.children.length > 0
) {
node.data.expand = false
}
if (node.children && node.children.length > 0) {
node.children.forEach(child => {
_walk(child, false, enableUnExpand)
})
}
}
_walk(this.renderTree, true, !uid)

this.mindMap.render(() => {
if (isSetRootNodeCenter) {
this.setRootNodeCenter()
Expand Down Expand Up @@ -2035,19 +2062,39 @@ class Render {
}

// 高亮节点或子节点
highlightNode(node, range) {
highlightNode(node, range, style) {
// 如果当前正在渲染,那么不进行高亮,因为节点位置可能不正确
if (this.isRendering) return
const { highlightNodeBoxStyle = {} } = this.mindMap.opt
style = {
stroke: 'rgb(94, 200, 248)',
fill: 'transparent',
...(style || {})
}
// 尚未创建
if (!this.highlightBoxNode) {
this.highlightBoxNode = new Polygon()
.stroke({
color: highlightNodeBoxStyle.stroke || 'transparent'
color: style.stroke || 'transparent'
})
.fill({
color: highlightNodeBoxStyle.fill || 'transparent'
color: style.fill || 'transparent'
})
} else if (this.highlightBoxNodeStyle) {
// 样式更新了
if (
this.highlightBoxNodeStyle.stroke !== style.stroke ||
this.highlightBoxNodeStyle.fill !== style.fill
) {
this.highlightBoxNode
.stroke({
color: style.stroke || 'transparent'
})
.fill({
color: style.fill || 'transparent'
})
}
}
this.highlightBoxNodeStyle = { ...style }
let minx = Infinity,
miny = Infinity,
maxx = -Infinity,
Expand Down
48 changes: 39 additions & 9 deletions simple-mind-map/src/core/render/TextEdit.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ export default class TextEdit {
// 如果编辑过程中缩放画布了,那么缓存当前编辑的内容
this.cacheEditingText = ''
this.hasBodyMousedown = false
this.textNodePaddingX = 5
this.textNodePaddingY = 3
this.bindEvent()
}

Expand Down Expand Up @@ -214,7 +216,7 @@ export default class TextEdit {
this.registerTmpShortcut()
if (!this.textEditNode) {
this.textEditNode = document.createElement('div')
this.textEditNode.style.cssText = `position:fixed;box-sizing: border-box;background-color:#fff;box-shadow: 0 0 20px rgba(0,0,0,.5);padding: 3px 5px;margin-left: -5px;margin-top: -3px;outline: none; word-break: break-all;`
this.textEditNode.style.cssText = `position:fixed;box-sizing: border-box;background-color:#fff;box-shadow: 0 0 20px rgba(0,0,0,.5);padding: ${this.textNodePaddingY}px ${this.textNodePaddingX}px;margin-left: -5px;margin-top: -3px;outline: none; word-break: break-all;`
this.textEditNode.setAttribute('contenteditable', true)
this.textEditNode.addEventListener('keyup', e => {
e.stopPropagation()
Expand All @@ -240,6 +242,13 @@ export default class TextEdit {
handleInputPasteText(e)
}
})
this.textEditNode.addEventListener('input', () => {
this.mindMap.emit('node_text_edit_change', {
node: this.currentNode,
text: this.getEditText(),
richText: false
})
})
const targetNode =
this.mindMap.opt.customInnerElsAppendTo || document.body
targetNode.appendChild(this.textEditNode)
Expand All @@ -256,8 +265,10 @@ export default class TextEdit {
node.style.domText(this.textEditNode, scale, isMultiLine)
this.textEditNode.style.zIndex = nodeTextEditZIndex
this.textEditNode.innerHTML = textLines.join('<br>')
this.textEditNode.style.minWidth = rect.width + 10 + 'px'
this.textEditNode.style.minHeight = rect.height + 6 + 'px'
this.textEditNode.style.minWidth =
rect.width + this.textNodePaddingX * 2 + 'px'
this.textEditNode.style.minHeight =
rect.height + this.textNodePaddingY * 2 + 'px'
this.textEditNode.style.left = rect.left + 'px'
this.textEditNode.style.top = rect.top + 'px'
this.textEditNode.style.display = 'block'
Expand All @@ -280,6 +291,24 @@ export default class TextEdit {
this.cacheEditingText = ''
}

// 更新文本编辑框的大小和位置
updateTextEditNode() {
if (this.mindMap.richText) {
this.mindMap.richText.updateTextEditNode()
return
}
if (!this.showTextEdit || !this.currentNode) {
return
}
const rect = this.currentNode._textData.node.node.getBoundingClientRect()
this.textEditNode.style.minWidth =
rect.width + this.textNodePaddingX * 2 + 'px'
this.textEditNode.style.minHeight =
rect.height + this.textNodePaddingY * 2 + 'px'
this.textEditNode.style.left = rect.left + 'px'
this.textEditNode.style.top = rect.top + 'px'
}

// 删除文本编辑元素
removeTextEditEl() {
if (this.mindMap.richText) {
Expand Down Expand Up @@ -313,12 +342,7 @@ export default class TextEdit {
}
this.mindMap.render()
})
this.mindMap.emit(
'hide_text_edit',
this.textEditNode,
this.renderer.activeNodeList,
this.currentNode
)
const currentNode = this.currentNode
this.currentNode = null
this.textEditNode.style.display = 'none'
this.textEditNode.innerHTML = ''
Expand All @@ -327,6 +351,12 @@ export default class TextEdit {
this.textEditNode.style.fontWeight = 'normal'
this.textEditNode.style.transform = 'translateY(0)'
this.showTextEdit = false
this.mindMap.emit(
'hide_text_edit',
this.textEditNode,
this.renderer.activeNodeList,
currentNode
)
}

// 获取当前正在编辑中的节点实例
Expand Down
2 changes: 2 additions & 0 deletions simple-mind-map/src/core/render/node/MindMapNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ class MindMapNode {
this.lineDraw = this.mindMap.lineDraw
// 样式实例
this.style = new Style(this)
// 节点当前生效的全部样式
this.effectiveStyles = {}
// 形状实例
this.shapeInstance = new Shape(this)
this.shapePadding = {
Expand Down
Loading

0 comments on commit 075bf54

Please sign in to comment.