mirror of
https://github.com/wanglin2/mind-map.git
synced 2026-02-24 18:38:26 +08:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9fe94bfc21 | ||
|
|
6be6f6ee8a | ||
|
|
83ce090402 | ||
|
|
250ff30704 | ||
|
|
55d7d0a846 | ||
|
|
0b3d2cedbd | ||
|
|
de025d9bc7 | ||
|
|
79a39f993d | ||
|
|
0fa731c3a2 | ||
|
|
34eece8fcf | ||
|
|
790662ad0c | ||
|
|
7d83a3635f | ||
|
|
546cf27b33 | ||
|
|
e59d419708 | ||
|
|
2d50106ce7 | ||
|
|
70c32e3c74 | ||
|
|
a0f56473ee | ||
|
|
51dcb1f54f | ||
|
|
9e34fd6174 |
@@ -226,4 +226,8 @@ const mindMap = new MindMap({
|
||||
<img src="./web/src/assets/avatar/moom.jpg" style="width: 50px;height: 50px;" />
|
||||
<span>moom</span>
|
||||
</span>
|
||||
<span>
|
||||
<img src="./web/src/assets/avatar/张扬.png" style="width: 50px;height: 50px;" />
|
||||
<span>张扬</span>
|
||||
</span>
|
||||
</p>
|
||||
@@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1,maximum-scale=1,minimum-scale=1"><link rel="icon" href="dist/logo.ico"><title>思绪思维导图</title><script>// 自定义静态资源的路径
|
||||
window.externalPublicPath = './dist/'
|
||||
// 接管应用
|
||||
window.takeOverApp = false</script><link href="dist/css/chunk-vendors.css?6450bdeb4871438bb6e4" rel="stylesheet"><link href="dist/css/app.css?6450bdeb4871438bb6e4" rel="stylesheet"></head><body><noscript><strong>We're sorry but thoughts doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script>const getDataFromBackend = () => {
|
||||
window.takeOverApp = false</script><link href="dist/css/chunk-vendors.css?7820598bfce2a2653e5c" rel="stylesheet"><link href="dist/css/app.css?7820598bfce2a2653e5c" rel="stylesheet"></head><body><noscript><strong>We're sorry but thoughts doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script>const getDataFromBackend = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
resolve({
|
||||
@@ -66,4 +66,4 @@
|
||||
// 可以通过window.$bus.$on()来监听应用的一些事件
|
||||
// 实例化页面
|
||||
window.initApp()
|
||||
}</script><script src="dist/js/chunk-vendors.js?6450bdeb4871438bb6e4"></script><script src="dist/js/app.js?6450bdeb4871438bb6e4"></script></body></html>
|
||||
}</script><script src="dist/js/chunk-vendors.js?7820598bfce2a2653e5c"></script><script src="dist/js/app.js?7820598bfce2a2653e5c"></script></body></html>
|
||||
@@ -487,6 +487,12 @@ class MindMap {
|
||||
// 销毁
|
||||
destroy() {
|
||||
this.emit('beforeDestroy')
|
||||
// 清除节点编辑框
|
||||
this.renderer.textEdit.hideEditTextBox()
|
||||
// 清除关联线文字编辑框
|
||||
if (this.associativeLine) {
|
||||
this.associativeLine.hideEditTextBox()
|
||||
}
|
||||
// 移除插件
|
||||
;[...MindMap.pluginList].forEach(plugin => {
|
||||
if (this[plugin.instanceName].beforePluginDestroy) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "simple-mind-map",
|
||||
"version": "0.9.0",
|
||||
"version": "0.9.1",
|
||||
"description": "一个简单的web在线思维导图",
|
||||
"authors": [
|
||||
{
|
||||
|
||||
@@ -229,6 +229,11 @@ export const CONSTANTS = {
|
||||
SCROLL_BAR_DIR: {
|
||||
VERTICAL: 'vertical',
|
||||
HORIZONTAL: 'horizontal'
|
||||
},
|
||||
CREATE_NEW_NODE_BEHAVIOR: {
|
||||
DEFAULT: 'default',
|
||||
NOT_ACTIVE: 'notActive',
|
||||
ACTIVE_ONLY: 'activeOnly'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -351,3 +356,14 @@ export const cssContent = `
|
||||
stroke-width: 2;
|
||||
}
|
||||
`
|
||||
|
||||
// html自闭合标签列表
|
||||
export const selfCloseTagList = [
|
||||
'img',
|
||||
'br',
|
||||
'hr',
|
||||
'input',
|
||||
'link',
|
||||
'meta',
|
||||
'area'
|
||||
]
|
||||
|
||||
@@ -56,11 +56,11 @@ export const defaultOpt = {
|
||||
// 可以传一个函数,回调参数为事件对象
|
||||
customHandleMousewheel: null,
|
||||
// 鼠标滚动的行为,如果customHandleMousewheel传了自定义函数,这个属性不生效
|
||||
mousewheelAction: CONSTANTS.MOUSE_WHEEL_ACTION.ZOOM, // zoom(放大缩小)、move(上下移动)
|
||||
mousewheelAction: CONSTANTS.MOUSE_WHEEL_ACTION.MOVE, // zoom(放大缩小)、move(上下移动)
|
||||
// 当mousewheelAction设为move时,可以通过该属性控制鼠标滚动一下视图移动的步长,单位px
|
||||
mousewheelMoveStep: 100,
|
||||
// 当mousewheelAction设为zoom时,默认向前滚动是缩小,向后滚动是放大,如果该属性设为true,那么会反过来
|
||||
mousewheelZoomActionReverse: false,
|
||||
// 当mousewheelAction设为zoom时,或者按住Ctrl键时,默认向前滚动是缩小,向后滚动是放大,如果该属性设为true,那么会反过来
|
||||
mousewheelZoomActionReverse: true,
|
||||
// 默认插入的二级节点的文字
|
||||
defaultInsertSecondLevelNodeText: '二级节点',
|
||||
// 默认插入的二级以下节点的文字
|
||||
@@ -210,8 +210,8 @@ export const defaultOpt = {
|
||||
tagsColorMap: {},
|
||||
// 节点协作样式配置
|
||||
cooperateStyle: {
|
||||
avatarSize: 22,// 头像大小
|
||||
fontSize: 12,// 如果是文字头像,那么文字的大小
|
||||
avatarSize: 22, // 头像大小
|
||||
fontSize: 12 // 如果是文字头像,那么文字的大小
|
||||
},
|
||||
// 关联线是否始终显示在节点上层
|
||||
// false:即创建关联线和激活关联线时处于最顶层,其他情况下处于节点下方
|
||||
@@ -229,5 +229,12 @@ export const defaultOpt = {
|
||||
highlightNodeBoxStyle: {
|
||||
stroke: 'rgb(94, 200, 248)',
|
||||
fill: 'transparent'
|
||||
}
|
||||
},
|
||||
// 创建新节点时的行为
|
||||
/*
|
||||
DEFAULT :默认会激活新创建的节点,并且进入编辑模式。如果同时创建了多个新节点,那么只会激活而不会进入编辑模式
|
||||
NOT_ACTIVE : 不激活新创建的节点
|
||||
ACTIVE_ONLY : 只激活新创建的节点,不进入编辑模式
|
||||
*/
|
||||
createNewNodeBehavior: CONSTANTS.CREATE_NEW_NODE_BEHAVIOR.DEFAULT
|
||||
}
|
||||
|
||||
@@ -133,18 +133,10 @@ class Event extends EventEmitter {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
let dir
|
||||
// 解决mac触控板双指缩放方向相反的问题
|
||||
if (e.ctrlKey) {
|
||||
if (e.deltaY > 0) dir = CONSTANTS.DIR.UP
|
||||
if (e.deltaY < 0) dir = CONSTANTS.DIR.DOWN
|
||||
if (e.deltaX > 0) dir = CONSTANTS.DIR.LEFT
|
||||
if (e.deltaX < 0) dir = CONSTANTS.DIR.RIGHT
|
||||
} else {
|
||||
if ((e.wheelDeltaY || e.detail) > 0) dir = CONSTANTS.DIR.UP
|
||||
if ((e.wheelDeltaY || e.detail) < 0) dir = CONSTANTS.DIR.DOWN
|
||||
if ((e.wheelDeltaX || e.detail) > 0) dir = CONSTANTS.DIR.LEFT
|
||||
if ((e.wheelDeltaX || e.detail) < 0) dir = CONSTANTS.DIR.RIGHT
|
||||
}
|
||||
if (e.deltaY < 0) dir = CONSTANTS.DIR.UP
|
||||
if (e.deltaY > 0) dir = CONSTANTS.DIR.DOWN
|
||||
if (e.deltaX < 0) dir = CONSTANTS.DIR.LEFT
|
||||
if (e.deltaX > 0) dir = CONSTANTS.DIR.RIGHT
|
||||
// 判断是否是触控板
|
||||
let isTouchPad = false
|
||||
// mac、windows
|
||||
|
||||
@@ -25,7 +25,8 @@ import {
|
||||
setDataToClipboard,
|
||||
getDataFromClipboard,
|
||||
htmlEscape,
|
||||
parseAddGeneralizationNodeList
|
||||
parseAddGeneralizationNodeList,
|
||||
checkNodeListIsEqual
|
||||
} from '../../utils'
|
||||
import { shapeList } from './node/Shape'
|
||||
import { lineStyleProps } from '../../themes/default'
|
||||
@@ -87,6 +88,9 @@ class Render {
|
||||
this.currentBeingPasteType = ''
|
||||
// 节点高亮框
|
||||
this.highlightBoxNode = null
|
||||
// 上一次节点激活数据
|
||||
this.lastActiveNode = null
|
||||
this.lastActiveNodeList = []
|
||||
// 布局
|
||||
this.setLayout()
|
||||
// 绑定事件
|
||||
@@ -335,6 +339,21 @@ class Render {
|
||||
})
|
||||
}
|
||||
|
||||
// 派发节点激活事件
|
||||
emitNodeActiveEvent(node = null, activeNodeList = [...this.activeNodeList]) {
|
||||
let isChange = false
|
||||
isChange = this.lastActiveNode !== node
|
||||
if (!isChange) {
|
||||
isChange = !checkNodeListIsEqual(this.lastActiveNodeList, activeNodeList)
|
||||
}
|
||||
if (!isChange) return
|
||||
this.lastActiveNode = node
|
||||
this.lastActiveNodeList = [...activeNodeList]
|
||||
this.mindMap.batchExecution.push('emitNodeActiveEvent', () => {
|
||||
this.mindMap.emit('node_active', node, activeNodeList)
|
||||
})
|
||||
}
|
||||
|
||||
// 鼠标点击画布时清空当前激活节点列表
|
||||
clearActiveNodeListOnDrawClick(e, eventType) {
|
||||
if (this.activeNodeList.length <= 0) return
|
||||
@@ -431,7 +450,7 @@ class Render {
|
||||
return
|
||||
}
|
||||
this.clearActiveNodeList()
|
||||
this.mindMap.emit('node_active', null, [])
|
||||
this.emitNodeActiveEvent(null, [])
|
||||
}
|
||||
|
||||
// 清除当前激活的节点列表
|
||||
@@ -505,6 +524,36 @@ class Render {
|
||||
}
|
||||
}
|
||||
|
||||
// 获取创建新节点的行为
|
||||
getNewNodeBehavior(openEdit = false, handleMultiNodes = false) {
|
||||
const { createNewNodeBehavior } = this.mindMap.opt
|
||||
let focusNewNode = false // 是否激活新节点
|
||||
let inserting = false // 新节点是否进入编辑模式
|
||||
switch (createNewNodeBehavior) {
|
||||
// 默认会激活新创建的节点,并且进入编辑模式。如果同时创建了多个新节点,那么只会激活而不会进入编辑模式
|
||||
case CONSTANTS.CREATE_NEW_NODE_BEHAVIOR.DEFAULT:
|
||||
focusNewNode = handleMultiNodes || !openEdit
|
||||
inserting = handleMultiNodes ? false : openEdit // 如果同时对多个节点插入子节点,那么无需进入编辑模式
|
||||
break
|
||||
// 不激活新创建的节点
|
||||
case CONSTANTS.CREATE_NEW_NODE_BEHAVIOR.NOT_ACTIVE:
|
||||
focusNewNode = false
|
||||
inserting = false
|
||||
break
|
||||
// 只激活新创建的节点,不进入编辑模式
|
||||
case CONSTANTS.CREATE_NEW_NODE_BEHAVIOR.ACTIVE_ONLY:
|
||||
focusNewNode = true
|
||||
inserting = false
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
return {
|
||||
focusNewNode,
|
||||
inserting
|
||||
}
|
||||
}
|
||||
|
||||
// 插入同级节点
|
||||
insertNode(
|
||||
openEdit = true,
|
||||
@@ -524,11 +573,15 @@ class Render {
|
||||
const list = appointNodes.length > 0 ? appointNodes : this.activeNodeList
|
||||
const handleMultiNodes = list.length > 1
|
||||
const isRichText = !!this.mindMap.richText
|
||||
const { focusNewNode, inserting } = this.getNewNodeBehavior(
|
||||
openEdit,
|
||||
handleMultiNodes
|
||||
)
|
||||
const params = {
|
||||
expand: true,
|
||||
richText: isRichText,
|
||||
resetRichText: isRichText,
|
||||
isActive: handleMultiNodes || !openEdit // 如果同时对多个节点插入子节点,那么需要把新增的节点设为激活状态。如果不进入编辑状态,那么也需要手动设为激活状态
|
||||
isActive: focusNewNode // 如果同时对多个节点插入子节点,那么需要把新增的节点设为激活状态。如果不进入编辑状态,那么也需要手动设为激活状态
|
||||
}
|
||||
// 动态指定的子节点数据也需要添加相关属性
|
||||
appointChildren = addDataToAppointNodes(appointChildren, {
|
||||
@@ -547,7 +600,7 @@ class Render {
|
||||
// 计算插入位置
|
||||
const index = getNodeDataIndex(node)
|
||||
const newNodeData = {
|
||||
inserting: handleMultiNodes ? false : openEdit, // 如果同时对多个节点插入子节点,那么无需进入编辑模式,
|
||||
inserting,
|
||||
data: {
|
||||
text: text,
|
||||
...params,
|
||||
@@ -559,7 +612,7 @@ class Render {
|
||||
parent.nodeData.children.splice(index + 1, 0, newNodeData)
|
||||
})
|
||||
// 如果同时对多个节点插入子节点,需要清除原来激活的节点
|
||||
if (handleMultiNodes || !openEdit) {
|
||||
if (focusNewNode) {
|
||||
this.clearActiveNodeList()
|
||||
}
|
||||
this.mindMap.render()
|
||||
@@ -575,11 +628,12 @@ class Render {
|
||||
this.textEdit.hideEditTextBox()
|
||||
const list = appointNodes.length > 0 ? appointNodes : this.activeNodeList
|
||||
const isRichText = !!this.mindMap.richText
|
||||
const { focusNewNode } = this.getNewNodeBehavior(false, true)
|
||||
const params = {
|
||||
expand: true,
|
||||
richText: isRichText,
|
||||
resetRichText: isRichText,
|
||||
isActive: true
|
||||
isActive: focusNewNode
|
||||
}
|
||||
nodeList = addDataToAppointNodes(nodeList, params)
|
||||
list.forEach(node => {
|
||||
@@ -595,7 +649,9 @@ class Render {
|
||||
)
|
||||
parent.nodeData.children.splice(index + 1, 0, ...newNodeList)
|
||||
})
|
||||
this.clearActiveNodeList()
|
||||
if (focusNewNode) {
|
||||
this.clearActiveNodeList()
|
||||
}
|
||||
this.mindMap.render()
|
||||
}
|
||||
|
||||
@@ -618,11 +674,15 @@ class Render {
|
||||
const list = appointNodes.length > 0 ? appointNodes : this.activeNodeList
|
||||
const handleMultiNodes = list.length > 1
|
||||
const isRichText = !!this.mindMap.richText
|
||||
const { focusNewNode, inserting } = this.getNewNodeBehavior(
|
||||
openEdit,
|
||||
handleMultiNodes
|
||||
)
|
||||
const params = {
|
||||
expand: true,
|
||||
richText: isRichText,
|
||||
resetRichText: isRichText,
|
||||
isActive: handleMultiNodes || !openEdit // 如果同时对多个节点插入子节点,那么需要把新增的节点设为激活状态。如果不进入编辑状态,那么也需要手动设为激活状态
|
||||
isActive: focusNewNode
|
||||
}
|
||||
// 动态指定的子节点数据也需要添加相关属性
|
||||
appointChildren = addDataToAppointNodes(appointChildren, {
|
||||
@@ -639,7 +699,7 @@ class Render {
|
||||
? defaultInsertSecondLevelNodeText
|
||||
: defaultInsertBelowSecondLevelNodeText
|
||||
const newNode = {
|
||||
inserting: handleMultiNodes ? false : openEdit, // 如果同时对多个节点插入子节点,那么无需进入编辑模式
|
||||
inserting,
|
||||
data: {
|
||||
text: text,
|
||||
uid: createUid(),
|
||||
@@ -655,7 +715,7 @@ class Render {
|
||||
})
|
||||
})
|
||||
// 如果同时对多个节点插入子节点,需要清除原来激活的节点
|
||||
if (handleMultiNodes || !openEdit) {
|
||||
if (focusNewNode) {
|
||||
this.clearActiveNodeList()
|
||||
}
|
||||
this.mindMap.render()
|
||||
@@ -671,11 +731,12 @@ class Render {
|
||||
this.textEdit.hideEditTextBox()
|
||||
const list = appointNodes.length > 0 ? appointNodes : this.activeNodeList
|
||||
const isRichText = !!this.mindMap.richText
|
||||
const { focusNewNode } = this.getNewNodeBehavior(false, true)
|
||||
const params = {
|
||||
expand: true,
|
||||
richText: isRichText,
|
||||
resetRichText: isRichText,
|
||||
isActive: true
|
||||
isActive: focusNewNode
|
||||
}
|
||||
childList = addDataToAppointNodes(childList, params)
|
||||
list.forEach(node => {
|
||||
@@ -692,7 +753,9 @@ class Render {
|
||||
expand: true
|
||||
})
|
||||
})
|
||||
this.clearActiveNodeList()
|
||||
if (focusNewNode) {
|
||||
this.clearActiveNodeList()
|
||||
}
|
||||
this.mindMap.render()
|
||||
}
|
||||
|
||||
@@ -710,11 +773,15 @@ class Render {
|
||||
const list = appointNodes.length > 0 ? appointNodes : this.activeNodeList
|
||||
const handleMultiNodes = list.length > 1
|
||||
const isRichText = !!this.mindMap.richText
|
||||
const { focusNewNode, inserting } = this.getNewNodeBehavior(
|
||||
openEdit,
|
||||
handleMultiNodes
|
||||
)
|
||||
const params = {
|
||||
expand: true,
|
||||
richText: isRichText,
|
||||
resetRichText: isRichText,
|
||||
isActive: handleMultiNodes || !openEdit // 如果同时对多个节点插入子节点,那么需要把新增的节点设为激活状态。如果不进入编辑状态,那么也需要手动设为激活状态
|
||||
isActive: focusNewNode
|
||||
}
|
||||
list.forEach(node => {
|
||||
if (node.isGeneralization || node.isRoot) {
|
||||
@@ -725,7 +792,7 @@ class Render {
|
||||
? defaultInsertSecondLevelNodeText
|
||||
: defaultInsertBelowSecondLevelNodeText
|
||||
const newNode = {
|
||||
inserting: handleMultiNodes ? false : openEdit, // 如果同时对多个节点插入子节点,那么无需进入编辑模式
|
||||
inserting,
|
||||
data: {
|
||||
text: text,
|
||||
uid: createUid(),
|
||||
@@ -740,7 +807,7 @@ class Render {
|
||||
parent.nodeData.children.splice(index, 1, newNode)
|
||||
})
|
||||
// 如果同时对多个节点插入子节点,需要清除原来激活的节点
|
||||
if (handleMultiNodes || !openEdit) {
|
||||
if (focusNewNode) {
|
||||
this.clearActiveNodeList()
|
||||
}
|
||||
this.mindMap.render()
|
||||
@@ -1602,11 +1669,6 @@ class Render {
|
||||
return res
|
||||
}
|
||||
|
||||
// 派发节点激活改变事件
|
||||
emitNodeActiveEvent() {
|
||||
this.mindMap.emit('node_active', null, [...this.activeNodeList])
|
||||
}
|
||||
|
||||
// 高亮节点或子节点
|
||||
highlightNode(node, range) {
|
||||
const { highlightNodeBoxStyle = {} } = this.mindMap.opt
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
selectAllInput,
|
||||
htmlEscape
|
||||
} from '../../utils'
|
||||
import { ERROR_TYPES } from '../../constants/constant'
|
||||
import { ERROR_TYPES, CONSTANTS } from '../../constants/constant'
|
||||
|
||||
// 节点文字编辑类
|
||||
export default class TextEdit {
|
||||
@@ -30,7 +30,9 @@ export default class TextEdit {
|
||||
this.onScale = this.onScale.bind(this)
|
||||
this.onKeydown = this.onKeydown.bind(this)
|
||||
// 节点双击事件
|
||||
this.mindMap.on('node_dblclick', this.show)
|
||||
this.mindMap.on('node_dblclick', (node, e, isInserting) => {
|
||||
this.show({ node, e, isInserting })
|
||||
})
|
||||
// 点击事件
|
||||
this.mindMap.on('draw_click', () => {
|
||||
// 隐藏文本编辑框
|
||||
@@ -54,12 +56,22 @@ export default class TextEdit {
|
||||
this.mindMap.on('before_node_active', () => {
|
||||
this.hideEditTextBox()
|
||||
})
|
||||
// 鼠标滚动事件
|
||||
this.mindMap.on('mousewheel', () => {
|
||||
if (
|
||||
this.mindMap.opt.mousewheelAction === CONSTANTS.MOUSE_WHEEL_ACTION.MOVE
|
||||
) {
|
||||
this.hideEditTextBox()
|
||||
}
|
||||
})
|
||||
// 注册编辑快捷键
|
||||
this.mindMap.keyCommand.addShortcut('F2', () => {
|
||||
if (this.renderer.activeNodeList.length <= 0) {
|
||||
return
|
||||
}
|
||||
this.show(this.renderer.activeNodeList[0])
|
||||
this.show({
|
||||
node: this.renderer.activeNodeList[0]
|
||||
})
|
||||
})
|
||||
this.mindMap.on('scale', this.onScale)
|
||||
// // 监听按键事件,判断是否自动进入文本编辑模式
|
||||
@@ -83,7 +95,12 @@ export default class TextEdit {
|
||||
const node = activeNodeList[0]
|
||||
// 当正在输入中文或英文或数字时,如果没有按下组合键,那么自动进入文本编辑模式
|
||||
if (node && this.checkIsAutoEnterTextEditKey(e)) {
|
||||
this.show(node, e, false, true)
|
||||
this.show({
|
||||
node,
|
||||
e,
|
||||
isInserting: false,
|
||||
isFromKeyDown: true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,12 +129,17 @@ export default class TextEdit {
|
||||
// 显示文本编辑框
|
||||
// isInserting:是否是刚创建的节点
|
||||
// isFromKeyDown:是否是在按键事件进入的编辑
|
||||
async show(node, e, isInserting = false, isFromKeyDown = false) {
|
||||
async show({
|
||||
node,
|
||||
isInserting = false,
|
||||
isFromKeyDown = false,
|
||||
isFromScale = false
|
||||
}) {
|
||||
// 使用了自定义节点内容那么不响应编辑事件
|
||||
if (node.isUseCustomNodeContent()) {
|
||||
return
|
||||
}
|
||||
let { beforeTextEdit } = this.mindMap.opt
|
||||
const { beforeTextEdit } = this.mindMap.opt
|
||||
if (typeof beforeTextEdit === 'function') {
|
||||
let isShow = false
|
||||
try {
|
||||
@@ -129,14 +151,21 @@ export default class TextEdit {
|
||||
if (!isShow) return
|
||||
}
|
||||
this.currentNode = node
|
||||
let { offsetLeft, offsetTop } = checkNodeOuter(this.mindMap, node)
|
||||
const { offsetLeft, offsetTop } = checkNodeOuter(this.mindMap, node)
|
||||
this.mindMap.view.translateXY(offsetLeft, offsetTop)
|
||||
let rect = node._textData.node.node.getBoundingClientRect()
|
||||
const rect = node._textData.node.node.getBoundingClientRect()
|
||||
const params = {
|
||||
node,
|
||||
rect,
|
||||
isInserting,
|
||||
isFromKeyDown,
|
||||
isFromScale
|
||||
}
|
||||
if (this.mindMap.richText) {
|
||||
this.mindMap.richText.showEditText(node, rect, isInserting, isFromKeyDown)
|
||||
this.mindMap.richText.showEditText(params)
|
||||
return
|
||||
}
|
||||
this.showEditTextBox(node, rect, isInserting, isFromKeyDown)
|
||||
this.showEditTextBox(params)
|
||||
}
|
||||
|
||||
// 处理画布缩放
|
||||
@@ -150,15 +179,20 @@ export default class TextEdit {
|
||||
this.cacheEditingText = this.getEditText()
|
||||
this.showTextEdit = false
|
||||
}
|
||||
this.show(this.currentNode)
|
||||
this.show({
|
||||
node: this.currentNode,
|
||||
isFromScale: true
|
||||
})
|
||||
}
|
||||
|
||||
// 显示文本编辑框
|
||||
showEditTextBox(node, rect, isInserting, isFromKeyDown) {
|
||||
showEditTextBox({ node, rect, isInserting, isFromKeyDown, isFromScale }) {
|
||||
if (this.showTextEdit) return
|
||||
const { nodeTextEditZIndex, textAutoWrapWidth, selectTextOnEnterEditText } =
|
||||
this.mindMap.opt
|
||||
this.mindMap.emit('before_show_text_edit')
|
||||
if (!isFromScale) {
|
||||
this.mindMap.emit('before_show_text_edit')
|
||||
}
|
||||
this.registerTmpShortcut()
|
||||
if (!this.textEditNode) {
|
||||
this.textEditNode = document.createElement('div')
|
||||
|
||||
@@ -179,6 +179,7 @@ class Node {
|
||||
let { isUseCustomNodeContent, customCreateNodeContent } = this.mindMap.opt
|
||||
if (isUseCustomNodeContent && customCreateNodeContent) {
|
||||
this._customNodeContent = customCreateNodeContent(this)
|
||||
this._customNodeContent.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml')
|
||||
}
|
||||
// 如果没有返回内容,那么还是使用内置的节点内容
|
||||
if (this._customNodeContent) return
|
||||
@@ -441,9 +442,7 @@ class Node {
|
||||
this.mindMap.renderer[
|
||||
isActive ? 'removeNodeFromActiveList' : 'addNodeToActiveList'
|
||||
](this)
|
||||
this.mindMap.emit('node_active', isActive ? null : this, [
|
||||
...this.mindMap.renderer.activeNodeList
|
||||
])
|
||||
this.renderer.emitNodeActiveEvent(isActive ? null : this)
|
||||
}
|
||||
this.mindMap.emit('node_mousedown', this, e)
|
||||
})
|
||||
@@ -474,7 +473,7 @@ class Node {
|
||||
})
|
||||
// 双击事件
|
||||
this.group.on('dblclick', e => {
|
||||
if (this.mindMap.opt.readonly) {
|
||||
if (this.mindMap.opt.readonly || e.ctrlKey) {
|
||||
return
|
||||
}
|
||||
e.stopPropagation()
|
||||
@@ -520,7 +519,7 @@ class Node {
|
||||
this.mindMap.emit('before_node_active', this, this.renderer.activeNodeList)
|
||||
this.renderer.clearActiveNodeList()
|
||||
this.renderer.addNodeToActiveList(this)
|
||||
this.mindMap.emit('node_active', this, [...this.renderer.activeNodeList])
|
||||
this.renderer.emitNodeActiveEvent(this)
|
||||
}
|
||||
|
||||
// 更新节点
|
||||
|
||||
@@ -72,7 +72,7 @@ class View {
|
||||
return customHandleMousewheel(e)
|
||||
}
|
||||
// 鼠标滚轮事件控制缩放
|
||||
if (mousewheelAction === CONSTANTS.MOUSE_WHEEL_ACTION.ZOOM) {
|
||||
if (mousewheelAction === CONSTANTS.MOUSE_WHEEL_ACTION.ZOOM || e.ctrlKey) {
|
||||
if (disableMouseWheelZoom) return
|
||||
const { x: clientX, y: clientY } = this.mindMap.toPos(
|
||||
e.clientX,
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import { bfsWalk, throttle, getTopAncestorsFomNodeList, getNodeIndexInNodeList } from '../utils'
|
||||
import {
|
||||
bfsWalk,
|
||||
throttle,
|
||||
getTopAncestorsFomNodeList,
|
||||
getNodeIndexInNodeList
|
||||
} from '../utils'
|
||||
import Base from '../layouts/Base'
|
||||
|
||||
// 节点拖动插件
|
||||
@@ -108,9 +113,7 @@ class Drag extends Base {
|
||||
node.endDrag()
|
||||
})
|
||||
this.removeCloneNode()
|
||||
let overlapNodeUid = this.overlapNode
|
||||
? this.overlapNode.getData('uid')
|
||||
: ''
|
||||
let overlapNodeUid = this.overlapNode ? this.overlapNode.getData('uid') : ''
|
||||
let prevNodeUid = this.prevNode ? this.prevNode.getData('uid') : ''
|
||||
let nextNodeUid = this.nextNode ? this.nextNode.getData('uid') : ''
|
||||
// 存在重叠子节点,则移动作为其子节点
|
||||
@@ -162,12 +165,14 @@ class Drag extends Base {
|
||||
)
|
||||
this.mindMap.render()
|
||||
}
|
||||
if (this.isDragging) {
|
||||
this.mindMap.emit('node_dragend', {
|
||||
overlapNodeUid,
|
||||
prevNodeUid,
|
||||
nextNodeUid
|
||||
})
|
||||
}
|
||||
this.reset()
|
||||
this.mindMap.emit('node_dragend', {
|
||||
overlapNodeUid,
|
||||
prevNodeUid,
|
||||
nextNodeUid
|
||||
})
|
||||
}
|
||||
|
||||
// 拖动中
|
||||
|
||||
@@ -3,7 +3,8 @@ import {
|
||||
downloadFile,
|
||||
readBlob,
|
||||
removeHTMLEntities,
|
||||
resizeImgSize
|
||||
resizeImgSize,
|
||||
handleSelfCloseTags
|
||||
} from '../utils'
|
||||
import { SVG } from '@svgdotjs/svg.js'
|
||||
import drawBackgroundImageToCanvas from '../utils/simulateCSSBackgroundInCanvas'
|
||||
@@ -20,7 +21,7 @@ class Export {
|
||||
// 导出
|
||||
async export(type, isDownload = true, name = '思维导图', ...args) {
|
||||
if (this[type]) {
|
||||
let result = await this[type](name, ...args)
|
||||
const result = await this[type](name, ...args)
|
||||
if (isDownload && type !== 'pdf') {
|
||||
downloadFile(result, name + '.' + type)
|
||||
}
|
||||
@@ -30,6 +31,20 @@ class Export {
|
||||
}
|
||||
}
|
||||
|
||||
// 创建图片url转换任务
|
||||
createTransformImgTaskList(svg, tagName, propName, getUrlFn) {
|
||||
const imageList = svg.find(tagName)
|
||||
return imageList.map(async item => {
|
||||
const imgUlr = getUrlFn(item)
|
||||
// 已经是data:URL形式不用转换
|
||||
if (/^data:/.test(imgUlr) || imgUlr === 'none') {
|
||||
return
|
||||
}
|
||||
const imgData = await imgToDataUrl(imgUlr)
|
||||
item.attr(propName, imgData)
|
||||
})
|
||||
}
|
||||
|
||||
// 获取svg数据
|
||||
async getSvgData() {
|
||||
let { exportPaddingX, exportPaddingY } = this.mindMap.opt
|
||||
@@ -37,19 +52,34 @@ class Export {
|
||||
paddingX: exportPaddingX,
|
||||
paddingY: exportPaddingY
|
||||
})
|
||||
// 把图片的url转换成data:url类型,否则导出会丢失图片
|
||||
let imageList = svg.find('image')
|
||||
let task = imageList.map(async item => {
|
||||
let imgUlr = item.attr('href') || item.attr('xlink:href')
|
||||
// 已经是data:URL形式不用转换
|
||||
if (/^data:/.test(imgUlr) || imgUlr === 'none') {
|
||||
return
|
||||
// svg的image标签,把图片的url转换成data:url类型,否则导出会丢失图片
|
||||
const task1 = this.createTransformImgTaskList(
|
||||
svg,
|
||||
'image',
|
||||
'href',
|
||||
item => {
|
||||
return item.attr('href') || item.attr('xlink:href')
|
||||
}
|
||||
let imgData = await imgToDataUrl(imgUlr)
|
||||
item.attr('href', imgData)
|
||||
)
|
||||
// html的img标签
|
||||
const task2 = this.createTransformImgTaskList(svg, 'img', 'src', item => {
|
||||
return item.attr('src')
|
||||
})
|
||||
await Promise.all(task)
|
||||
if (imageList.length > 0) {
|
||||
const taskList = [...task1, ...task2]
|
||||
await Promise.all(taskList)
|
||||
// 开启了节点富文本编辑,需要增加一些样式
|
||||
let isAddResetCss
|
||||
if (this.mindMap.richText) {
|
||||
const foreignObjectList = svg.find('foreignObject')
|
||||
if (foreignObjectList.length > 0) {
|
||||
foreignObjectList[0].add(
|
||||
SVG(`<style>${this.mindMap.opt.resetCss}</style>`)
|
||||
)
|
||||
isAddResetCss = true
|
||||
}
|
||||
}
|
||||
// svg节点内容有变,需要重新获取html字符串
|
||||
if (taskList.length > 0 || isAddResetCss) {
|
||||
svgHTML = svg.svg()
|
||||
}
|
||||
return {
|
||||
@@ -131,7 +161,7 @@ class Export {
|
||||
// 在canvas上绘制思维导图背景
|
||||
drawBackgroundToCanvas(ctx, width, height) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let {
|
||||
const {
|
||||
backgroundColor = '#fff',
|
||||
backgroundImage,
|
||||
backgroundRepeat = 'no-repeat',
|
||||
@@ -175,7 +205,7 @@ class Export {
|
||||
// 在svg上绘制思维导图背景
|
||||
drawBackgroundToSvg(svg) {
|
||||
return new Promise(async resolve => {
|
||||
let {
|
||||
const {
|
||||
backgroundColor = '#fff',
|
||||
backgroundImage,
|
||||
backgroundRepeat = 'repeat'
|
||||
@@ -184,7 +214,7 @@ class Export {
|
||||
svg.css('background-color', backgroundColor)
|
||||
// 背景图片
|
||||
if (backgroundImage && backgroundImage !== 'none') {
|
||||
let imgDataUrl = await imgToDataUrl(backgroundImage)
|
||||
const imgDataUrl = await imgToDataUrl(backgroundImage)
|
||||
svg.css('background-image', `url(${imgDataUrl})`)
|
||||
svg.css('background-repeat', backgroundRepeat)
|
||||
resolve()
|
||||
@@ -200,35 +230,10 @@ class Export {
|
||||
* 方法2.把svg的图片提取出来再挨个绘制到canvas里,最后一起转换
|
||||
*/
|
||||
async png(name, transparent = false, checkRotate, compress) {
|
||||
let { node, str } = await this.getSvgData()
|
||||
// 如果开启了富文本,则使用htmltocanvas转换为图片
|
||||
if (this.mindMap.richText) {
|
||||
// 覆盖html默认的样式
|
||||
let foreignObjectList = node.find('foreignObject')
|
||||
if (foreignObjectList.length > 0) {
|
||||
foreignObjectList[0].add(
|
||||
SVG(`<style>${this.mindMap.opt.resetCss}</style>`)
|
||||
)
|
||||
}
|
||||
str = node.svg()
|
||||
// 使用其他库(html2canvas、dom-to-image-more等)来完成导出
|
||||
// let res = await this.mindMap.richText.handleExportPng(node.node)
|
||||
// let imgDataUrl = await this.svgToPng(
|
||||
// res,
|
||||
// transparent,
|
||||
// checkRotate
|
||||
// )
|
||||
// return imgDataUrl
|
||||
}
|
||||
str = removeHTMLEntities(str)
|
||||
// 转换成blob数据
|
||||
let blob = new Blob([str], {
|
||||
type: 'image/svg+xml'
|
||||
})
|
||||
// 转换成data:url数据
|
||||
let svgUrl = await readBlob(blob)
|
||||
const { str } = await this.getSvgData()
|
||||
const svgUrl = await this.fixSvgStrAndToBlob(str)
|
||||
// 绘制到canvas上
|
||||
let res = await this.svgToPng(svgUrl, transparent, checkRotate, compress)
|
||||
const res = await this.svgToPng(svgUrl, transparent, checkRotate, compress)
|
||||
return res
|
||||
}
|
||||
|
||||
@@ -237,7 +242,7 @@ class Export {
|
||||
if (!this.mindMap.doExportPDF) {
|
||||
throw new Error('请注册ExportPDF插件')
|
||||
}
|
||||
let img = await this.png(
|
||||
const img = await this.png(
|
||||
'',
|
||||
false,
|
||||
(width, height) => {
|
||||
@@ -263,51 +268,50 @@ class Export {
|
||||
}
|
||||
|
||||
// 导出为svg
|
||||
// plusCssText:附加的css样式,如果svg中存在dom节点,想要设置一些针对节点的样式可以通过这个参数传入
|
||||
async svg(name) {
|
||||
let { node } = await this.getSvgData()
|
||||
// 开启了节点富文本编辑
|
||||
if (this.mindMap.richText) {
|
||||
let foreignObjectList = node.find('foreignObject')
|
||||
if (foreignObjectList.length > 0) {
|
||||
foreignObjectList[0].add(
|
||||
SVG(`<style>${this.mindMap.opt.resetCss}</style>`)
|
||||
)
|
||||
}
|
||||
}
|
||||
const { node } = await this.getSvgData()
|
||||
node.first().before(SVG(`<title>${name}</title>`))
|
||||
await this.drawBackgroundToSvg(node)
|
||||
let str = node.svg()
|
||||
const str = node.svg()
|
||||
const res = await this.fixSvgStrAndToBlob(str)
|
||||
return res
|
||||
}
|
||||
|
||||
// 修复svg字符串,并且转换为blob数据
|
||||
async fixSvgStrAndToBlob(str) {
|
||||
// 移除字符串中的html实体
|
||||
str = removeHTMLEntities(str)
|
||||
// 给html自闭合标签添加闭合状态
|
||||
str = handleSelfCloseTags(str)
|
||||
// 转换成blob数据
|
||||
let blob = new Blob([str], {
|
||||
const blob = new Blob([str], {
|
||||
type: 'image/svg+xml'
|
||||
})
|
||||
let res = await readBlob(blob)
|
||||
const res = await readBlob(blob)
|
||||
return res
|
||||
}
|
||||
|
||||
// 导出为json
|
||||
async json(name, withConfig = true) {
|
||||
let data = this.mindMap.getData(withConfig)
|
||||
let str = JSON.stringify(data)
|
||||
let blob = new Blob([str])
|
||||
let res = await readBlob(blob)
|
||||
const data = this.mindMap.getData(withConfig)
|
||||
const str = JSON.stringify(data)
|
||||
const blob = new Blob([str])
|
||||
const res = await readBlob(blob)
|
||||
return res
|
||||
}
|
||||
|
||||
// 专有文件,其实就是json文件
|
||||
async smm(name, withConfig) {
|
||||
let res = await this.json(name, withConfig)
|
||||
const res = await this.json(name, withConfig)
|
||||
return res
|
||||
}
|
||||
|
||||
// markdown文件
|
||||
async md() {
|
||||
let data = this.mindMap.getData()
|
||||
let content = transformToMarkdown(data)
|
||||
let blob = new Blob([content])
|
||||
let res = await readBlob(blob)
|
||||
const data = this.mindMap.getData()
|
||||
const content = transformToMarkdown(data)
|
||||
const blob = new Blob([content])
|
||||
const res = await readBlob(blob)
|
||||
return res
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ class Painter {
|
||||
}
|
||||
|
||||
onEndPainter() {
|
||||
if (!this.isInPainter) return
|
||||
this.endPainter()
|
||||
this.mindMap.emit('painter_end')
|
||||
}
|
||||
|
||||
@@ -153,7 +153,7 @@ class RichText {
|
||||
}
|
||||
|
||||
// 显示文本编辑控件
|
||||
showEditText(node, rect, isInserting, isFromKeyDown) {
|
||||
showEditText({ node, rect, isInserting, isFromKeyDown, isFromScale }) {
|
||||
if (this.showTextEdit) {
|
||||
return
|
||||
}
|
||||
@@ -167,7 +167,9 @@ class RichText {
|
||||
this.node = node
|
||||
this.isInserting = isInserting
|
||||
if (!rect) rect = node._textData.node.node.getBoundingClientRect()
|
||||
this.mindMap.emit('before_show_text_edit')
|
||||
if (!isFromScale) {
|
||||
this.mindMap.emit('before_show_text_edit')
|
||||
}
|
||||
this.mindMap.renderer.textEdit.registerTmpShortcut()
|
||||
// 原始宽高
|
||||
let g = node._textData.node
|
||||
@@ -571,7 +573,7 @@ class RichText {
|
||||
setNotActiveNodeStyle(node, style) {
|
||||
const config = this.normalStyleToRichTextStyle(style)
|
||||
if (Object.keys(config).length > 0) {
|
||||
this.showEditText(node)
|
||||
this.showEditText({ node })
|
||||
this.formatAllText(config)
|
||||
this.hideEditText([node])
|
||||
}
|
||||
|
||||
@@ -65,6 +65,9 @@ class Search {
|
||||
this.currentIndex = -1
|
||||
this.notResetSearchText = false
|
||||
this.isSearching = false
|
||||
if (this.mindMap.opt.readonly) {
|
||||
this.mindMap.renderer.closeHighlightNode()
|
||||
}
|
||||
this.emitEvent()
|
||||
}
|
||||
|
||||
@@ -96,6 +99,10 @@ class Search {
|
||||
this.mindMap.execCommand('GO_TARGET_NODE', currentNode, () => {
|
||||
this.notResetSearchText = false
|
||||
callback()
|
||||
// 只读模式下节点无法激活,所以通过高亮的方式
|
||||
if (this.mindMap.opt.readonly) {
|
||||
this.mindMap.renderer.highlightNode(currentNode)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -133,9 +133,7 @@ class Select {
|
||||
}
|
||||
}
|
||||
if (isNumChange || isNodeChange) {
|
||||
this.mindMap.emit('node_active', null, [
|
||||
...this.mindMap.renderer.activeNodeList
|
||||
])
|
||||
this.mindMap.renderer.emitNodeActiveEvent()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ class BatchExecution {
|
||||
// 添加任务
|
||||
push(name, fn) {
|
||||
if (this.has[name]) {
|
||||
this.replaceTask(name, fn)
|
||||
return
|
||||
}
|
||||
this.has[name] = true
|
||||
@@ -22,6 +23,19 @@ class BatchExecution {
|
||||
this.nextTick()
|
||||
}
|
||||
|
||||
// 替换任务
|
||||
replaceTask(name, fn) {
|
||||
const index = this.queue.findIndex(item => {
|
||||
return item.name === name
|
||||
})
|
||||
if (index !== -1) {
|
||||
this.queue[index] = {
|
||||
name,
|
||||
fn
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 执行队列
|
||||
flush() {
|
||||
let fns = this.queue.slice(0)
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { nodeDataNoStylePropList } from '../constants/constant'
|
||||
import {
|
||||
nodeDataNoStylePropList,
|
||||
selfCloseTagList
|
||||
} from '../constants/constant'
|
||||
import MersenneTwister from './mersenneTwister'
|
||||
// 深度优先遍历树
|
||||
export const walk = (
|
||||
@@ -989,3 +992,29 @@ export const removeFromParentNodeData = node => {
|
||||
if (index === -1) return
|
||||
node.parent.nodeData.children.splice(index, 1)
|
||||
}
|
||||
|
||||
// 给html自闭合标签添加闭合状态
|
||||
export const handleSelfCloseTags = str => {
|
||||
selfCloseTagList.forEach(tagName => {
|
||||
str = str.replaceAll(
|
||||
new RegExp(`<${tagName}([^>]*)>`, 'g'),
|
||||
`<${tagName} $1 />`
|
||||
)
|
||||
})
|
||||
return str
|
||||
}
|
||||
|
||||
// 检查两个节点列表是否包含的节点是一样的
|
||||
export const checkNodeListIsEqual = (list1, list2) => {
|
||||
if (list1.length !== list2.length) return false
|
||||
for (let i = 0; i < list1.length; i++) {
|
||||
if (
|
||||
!list2.find(item => {
|
||||
return item.uid === list1[i].uid
|
||||
})
|
||||
) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
7
simple-mind-map/types/index.d.ts
vendored
7
simple-mind-map/types/index.d.ts
vendored
@@ -74,6 +74,7 @@ declare class MindMap {
|
||||
richTextEditFakeInPlace: boolean;
|
||||
customHandleClipboardText: any;
|
||||
disableMouseWheelZoom: boolean;
|
||||
disableTouchZoom: boolean;
|
||||
errorHandler: (code: any, error: any) => void;
|
||||
resetCss: string;
|
||||
enableDblclickBackToRootNode: boolean;
|
||||
@@ -103,6 +104,12 @@ declare class MindMap {
|
||||
defaultGeneralizationText: string;
|
||||
handleIsSplitByWrapOnPasteCreateNewNode: any;
|
||||
addHistoryTime: number;
|
||||
isDisableDrag: boolean;
|
||||
highlightNodeBoxStyle: {
|
||||
stroke: string;
|
||||
fill: string;
|
||||
};
|
||||
createNewNodeBehavior: string;
|
||||
});
|
||||
opt: any;
|
||||
el: any;
|
||||
|
||||
@@ -80,6 +80,11 @@ export namespace CONSTANTS {
|
||||
const VERTICAL: string;
|
||||
const HORIZONTAL: string;
|
||||
}
|
||||
namespace CREATE_NEW_NODE_BEHAVIOR {
|
||||
const DEFAULT: string;
|
||||
const NOT_ACTIVE: string;
|
||||
const ACTIVE_ONLY: string;
|
||||
}
|
||||
}
|
||||
export const initRootNodePositionMap: {
|
||||
[x: string]: number;
|
||||
@@ -107,3 +112,4 @@ export namespace a4Size {
|
||||
const height: number;
|
||||
}
|
||||
export const cssContent: "\n /* 鼠标hover和激活时渲染的矩形 */\n .smm-hover-node{\n display: none;\n opacity: 0.6;\n stroke-width: 1;\n }\n\n .smm-node:not(.smm-node-dragging):hover .smm-hover-node{\n display: block;\n }\n\n .smm-node.active .smm-hover-node{\n display: block;\n opacity: 1;\n stroke-width: 2;\n }\n";
|
||||
export const selfCloseTagList: string[];
|
||||
|
||||
@@ -70,6 +70,7 @@ export namespace defaultOpt {
|
||||
const richTextEditFakeInPlace: boolean;
|
||||
const customHandleClipboardText: any;
|
||||
const disableMouseWheelZoom: boolean;
|
||||
const disableTouchZoom: boolean;
|
||||
function errorHandler(code: any, error: any): void;
|
||||
const resetCss: string;
|
||||
const enableDblclickBackToRootNode: boolean;
|
||||
@@ -101,4 +102,11 @@ export namespace defaultOpt {
|
||||
const defaultGeneralizationText: string;
|
||||
const handleIsSplitByWrapOnPasteCreateNewNode: any;
|
||||
const addHistoryTime: number;
|
||||
const isDisableDrag: boolean;
|
||||
namespace highlightNodeBoxStyle {
|
||||
export const stroke: string;
|
||||
const fill_2: string;
|
||||
export { fill_2 as fill };
|
||||
}
|
||||
const createNewNodeBehavior: string;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@ export default class KeyCommand {
|
||||
save(): void;
|
||||
restore(): void;
|
||||
bindEvent(): void;
|
||||
onKeydown(e: any): void;
|
||||
unBindEvent(): void;
|
||||
checkKey(e: any, key: any): boolean;
|
||||
getOriginEventCodeArr(e: any): any[];
|
||||
hasCombinationKey(e: any): any;
|
||||
|
||||
@@ -20,6 +20,9 @@ declare class Render {
|
||||
beingPasteText: string;
|
||||
beingPasteImgSize: number;
|
||||
currentBeingPasteType: string;
|
||||
highlightBoxNode: any;
|
||||
lastActiveNode: any;
|
||||
lastActiveNodeList: any[];
|
||||
setLayout(): void;
|
||||
layout: MindMap | CatalogOrganization | OrganizationStructure | Timeline | VerticalTimeline;
|
||||
setData(data: any): void;
|
||||
@@ -66,6 +69,7 @@ declare class Render {
|
||||
goTargetNode(node: any, callback?: () => void): void;
|
||||
registerShortcutKeys(): void;
|
||||
toggleActiveExpand(): void;
|
||||
emitNodeActiveEvent(node?: any, activeNodeList?: any[]): void;
|
||||
clearActiveNodeListOnDrawClick(e: any, eventType: any): void;
|
||||
startTextEdit(): void;
|
||||
endTextEdit(): void;
|
||||
@@ -75,12 +79,17 @@ declare class Render {
|
||||
removeNodeFromActiveList(node: any): void;
|
||||
findActiveNodeIndex(node: any): any;
|
||||
backForward(type: any, step: any): void;
|
||||
getNewNodeBehavior(openEdit?: boolean, handleMultiNodes?: boolean): {
|
||||
focusNewNode: boolean;
|
||||
inserting: boolean;
|
||||
};
|
||||
copy(): void;
|
||||
cut(): void;
|
||||
paste(): void;
|
||||
onPaste(): Promise<void>;
|
||||
insertTo(node: any, exist: any, dir?: string): void;
|
||||
checkNodeLayerChange(node: any, toNode: any): void;
|
||||
deleteNodeGeneralization(node: any): void;
|
||||
getNextActiveNode(): any;
|
||||
copyNode(): any;
|
||||
toggleNodeExpand(node: any): void;
|
||||
@@ -89,7 +98,8 @@ declare class Render {
|
||||
setRootNodeCenter(): void;
|
||||
expandToNodeUid(uid: any, callback?: () => void): void;
|
||||
findNodeByUid(uid: any): any;
|
||||
emitNodeActiveEvent(): void;
|
||||
highlightNode(node: any, range: any): void;
|
||||
closeHighlightNode(): void;
|
||||
}
|
||||
import TextEdit from "./TextEdit";
|
||||
import MindMap from "../../layouts/MindMap";
|
||||
|
||||
@@ -7,11 +7,24 @@ export default class TextEdit {
|
||||
showTextEdit: boolean;
|
||||
cacheEditingText: string;
|
||||
bindEvent(): void;
|
||||
show(node: any, e: any, isInserting?: boolean, isFromKeyDown?: boolean): Promise<void>;
|
||||
show({ node, isInserting, isFromKeyDown, isFromScale }: {
|
||||
node: any;
|
||||
isInserting?: boolean;
|
||||
isFromKeyDown?: boolean;
|
||||
isFromScale?: boolean;
|
||||
}): Promise<void>;
|
||||
onScale(): void;
|
||||
onKeydown(e: any): void;
|
||||
unBindEvent(): void;
|
||||
checkIsAutoEnterTextEditKey(e: any): boolean;
|
||||
registerTmpShortcut(): void;
|
||||
showEditTextBox(node: any, rect: any, isInserting: any, isFromKeyDown: any): void;
|
||||
showEditTextBox({ node, rect, isInserting, isFromKeyDown, isFromScale }: {
|
||||
node: any;
|
||||
rect: any;
|
||||
isInserting: any;
|
||||
isFromKeyDown: any;
|
||||
isFromScale: any;
|
||||
}): void;
|
||||
getEditText(): any;
|
||||
hideEditTextBox(): any;
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ declare class Node {
|
||||
_tagData: any;
|
||||
_noteData: any;
|
||||
noteEl: any;
|
||||
noteContentIsShow: boolean;
|
||||
_expandBtn: any;
|
||||
_lastExpandBtnType: any;
|
||||
_showExpandBtn: boolean;
|
||||
@@ -47,8 +48,7 @@ declare class Node {
|
||||
_fillExpandNode: any;
|
||||
_userListGroup: any;
|
||||
_lines: any[];
|
||||
_generalizationLine: any;
|
||||
_generalizationNode: any;
|
||||
_generalizationList: any[];
|
||||
_unVisibleRectRegionNode: any;
|
||||
_isMouseenter: boolean;
|
||||
_rectInfo: {
|
||||
@@ -102,11 +102,14 @@ declare class Node {
|
||||
getShape(): any;
|
||||
hasCustomPosition(): boolean;
|
||||
ancestorHasCustomPosition(): boolean;
|
||||
ancestorHasGeneralization(): boolean;
|
||||
addChildren(node: any): void;
|
||||
styleLine(line: any, node: any): void;
|
||||
removeLine(): void;
|
||||
isAncestor(node: any): boolean;
|
||||
isParent(node: any): boolean;
|
||||
isBrother(node: any): any;
|
||||
getIndexInBrothers(): any;
|
||||
getPaddingVale(): {
|
||||
paddingX: any;
|
||||
paddingY: any;
|
||||
@@ -117,7 +120,17 @@ declare class Node {
|
||||
getSelfInhertStyle(prop: any): any;
|
||||
getBorderWidth(): any;
|
||||
getData(key: any): any;
|
||||
getPureData(removeActiveState?: boolean, removeId?: boolean): any;
|
||||
hasCustomStyle(): boolean;
|
||||
getRect(): any;
|
||||
getRectInSvg(): {
|
||||
left: any;
|
||||
right: any;
|
||||
top: any;
|
||||
bottom: any;
|
||||
width: number;
|
||||
height: number;
|
||||
};
|
||||
}
|
||||
import Style from "./Style";
|
||||
import Shape from "./Shape";
|
||||
|
||||
@@ -7,6 +7,7 @@ declare namespace _default {
|
||||
export { createHyperlinkNode };
|
||||
export { createTagNode };
|
||||
export { createNoteNode };
|
||||
export { getNoteContentPosition };
|
||||
export { measureCustomNodeContentSize };
|
||||
export { isUseCustomNodeContent };
|
||||
}
|
||||
@@ -38,6 +39,10 @@ declare function createNoteNode(): {
|
||||
declare class createNoteNode {
|
||||
noteEl: HTMLDivElement;
|
||||
}
|
||||
declare function getNoteContentPosition(): {
|
||||
left: any;
|
||||
top: any;
|
||||
};
|
||||
declare function measureCustomNodeContentSize(content: any): {
|
||||
width: any;
|
||||
height: any;
|
||||
|
||||
@@ -1,32 +1,38 @@
|
||||
declare namespace _default {
|
||||
export { formatGetGeneralization };
|
||||
export { checkHasGeneralization };
|
||||
export { checkHasSelfGeneralization };
|
||||
export { getGeneralizationNodeIndex };
|
||||
export { createGeneralizationNode };
|
||||
export { updateGeneralization };
|
||||
export { updateGeneralizationData };
|
||||
export { renderGeneralization };
|
||||
export { removeGeneralization };
|
||||
export { hideGeneralization };
|
||||
export { showGeneralization };
|
||||
export { setGeneralizationOpacity };
|
||||
export { handleGeneralizationMouseenter };
|
||||
export { handleGeneralizationMouseleave };
|
||||
}
|
||||
export default _default;
|
||||
declare function formatGetGeneralization(): any[];
|
||||
declare function checkHasGeneralization(): boolean;
|
||||
declare function checkHasSelfGeneralization(): boolean;
|
||||
declare function getGeneralizationNodeIndex(node: any): any;
|
||||
declare function createGeneralizationNode(): void;
|
||||
declare class createGeneralizationNode {
|
||||
_generalizationLine: any;
|
||||
_generalizationNode: Node;
|
||||
_generalizationNodeWidth: any;
|
||||
_generalizationNodeHeight: any;
|
||||
}
|
||||
declare function updateGeneralization(): void;
|
||||
declare function renderGeneralization(): void;
|
||||
declare class renderGeneralization {
|
||||
_generalizationNodeWidth: number;
|
||||
_generalizationNodeHeight: number;
|
||||
}
|
||||
declare function updateGeneralization(): void;
|
||||
declare function updateGeneralizationData(): void;
|
||||
declare function renderGeneralization(): void;
|
||||
declare function removeGeneralization(): void;
|
||||
declare class removeGeneralization {
|
||||
_generalizationLine: any;
|
||||
_generalizationNode: any;
|
||||
_generalizationList: any[];
|
||||
}
|
||||
declare function hideGeneralization(): void;
|
||||
declare function showGeneralization(): void;
|
||||
import Node from "./Node";
|
||||
declare function setGeneralizationOpacity(val: any): void;
|
||||
declare function handleGeneralizationMouseenter(): void;
|
||||
declare function handleGeneralizationMouseleave(): void;
|
||||
|
||||
16
simple-mind-map/types/src/layouts/Base.d.ts
vendored
16
simple-mind-map/types/src/layouts/Base.d.ts
vendored
@@ -39,6 +39,22 @@ declare class Base {
|
||||
generalizationLineMargin: any;
|
||||
generalizationNodeMargin: any;
|
||||
};
|
||||
getChildrenBoundaries(node: any, dir: any, startIndex: number, endIndex: any): {
|
||||
left: number;
|
||||
right: number;
|
||||
top: number;
|
||||
bottom: number;
|
||||
generalizationLineMargin: any;
|
||||
generalizationNodeMargin: any;
|
||||
};
|
||||
getNodeGeneralizationRenderBoundaries(item: any, dir: any): {
|
||||
left: any;
|
||||
right: any;
|
||||
top: any;
|
||||
bottom: any;
|
||||
generalizationLineMargin: any;
|
||||
generalizationNodeMargin: any;
|
||||
};
|
||||
getNodeActChildrenLength(node: any): any;
|
||||
}
|
||||
import Lru from "../utils/Lru";
|
||||
|
||||
@@ -4,5 +4,6 @@ declare class BatchExecution {
|
||||
queue: any[];
|
||||
nextTick: any;
|
||||
push(name: any, fn: any): void;
|
||||
replaceTask(name: any, fn: any): void;
|
||||
flush(): void;
|
||||
}
|
||||
|
||||
4
simple-mind-map/types/src/utils/index.d.ts
vendored
4
simple-mind-map/types/src/utils/index.d.ts
vendored
@@ -58,6 +58,8 @@ export function getObjectChangedProps(oldObject: any, newObject: any): {};
|
||||
export function checkIsNodeStyleDataKey(key: any): boolean;
|
||||
export function mergerIconList(list: any): any;
|
||||
export function getTopAncestorsFomNodeList(list: any): any[];
|
||||
export function checkHasSupSubRelation(list: any): boolean;
|
||||
export function parseAddGeneralizationNodeList(list: any): any[];
|
||||
export function checkTwoRectIsOverlap(minx1: any, maxx1: any, miny1: any, maxy1: any, minx2: any, maxx2: any, miny2: any, maxy2: any): boolean;
|
||||
export function focusInput(el: any): void;
|
||||
export function selectAllInput(el: any): void;
|
||||
@@ -75,3 +77,5 @@ export function getDataFromClipboard(): Promise<{
|
||||
img: any;
|
||||
}>;
|
||||
export function removeFromParentNodeData(node: any): void;
|
||||
export function handleSelfCloseTags(str: any): any;
|
||||
export function checkNodeListIsEqual(list1: any, list2: any): boolean;
|
||||
|
||||
BIN
web/src/assets/avatar/张扬.png
Normal file
BIN
web/src/assets/avatar/张扬.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 36 KiB |
@@ -314,6 +314,11 @@ export const shortcutKeyList = [
|
||||
name: 'Zoom out',
|
||||
value: 'Ctrl + -'
|
||||
},
|
||||
{
|
||||
icon: 'iconfangda',
|
||||
name: 'Zoom in/Zoom out',
|
||||
value: 'Ctrl + Mouse wheel'
|
||||
},
|
||||
{
|
||||
icon: 'icondingwei',
|
||||
name: 'Back root node',
|
||||
|
||||
@@ -381,6 +381,11 @@ export const shortcutKeyList = [
|
||||
name: '缩小',
|
||||
value: 'Ctrl + -'
|
||||
},
|
||||
{
|
||||
icon: 'iconfangda',
|
||||
name: '放大/缩小',
|
||||
value: 'Ctrl + 鼠标滚动'
|
||||
},
|
||||
{
|
||||
icon: 'icondingwei',
|
||||
name: '回到根节点',
|
||||
|
||||
@@ -47,6 +47,10 @@ export default {
|
||||
mousewheelZoomActionReverse: 'Mouse Wheel Zoom',
|
||||
mousewheelZoomActionReverse1: 'Zoom out forward and zoom in back',
|
||||
mousewheelZoomActionReverse2: 'Zoom in forward and zoom out back',
|
||||
createNewNodeBehavior: 'Behavior of creating new node',
|
||||
default: 'Active new node and editing',
|
||||
notActive: 'Not active new node',
|
||||
activeOnly: 'Only active new node but not editing',
|
||||
rootStyle: 'Root Node',
|
||||
associativeLineText: 'Associative line text',
|
||||
fontFamily: 'Font family',
|
||||
|
||||
@@ -47,6 +47,10 @@ export default {
|
||||
mousewheelZoomActionReverse: '鼠标滚轮缩放',
|
||||
mousewheelZoomActionReverse1: '向前缩小向后放大',
|
||||
mousewheelZoomActionReverse2: '向前放大向后缩小',
|
||||
createNewNodeBehavior: '创建新节点的行为',
|
||||
default: '激活新节点及进入编辑',
|
||||
notActive: '不激活新节点',
|
||||
activeOnly: '只激活新节点,不进入编辑',
|
||||
rootStyle: '根节点',
|
||||
associativeLineText: '关联线文字',
|
||||
fontFamily: '字体',
|
||||
|
||||
@@ -1,5 +1,37 @@
|
||||
# Changelog
|
||||
|
||||
## 0.9.1
|
||||
|
||||
Fix:
|
||||
|
||||
> 1.Fix the issue of exporting images, SVGs, and PDFs with errors when customizing node content.
|
||||
>
|
||||
> 2.Optimize the distribution of node activation events, do not distribute events when the activation node has not changed, and skip intermediate events when distributing multiple events in a short period of time.
|
||||
>
|
||||
> 3.Fix the issue where the edit box and node detach when scrolling the canvas with the mouse while the node is in editing mode.
|
||||
>
|
||||
> 4.Fix the issue of shortcut keys becoming invalid when zooming the canvas with the mouse wheel and then exiting node editing while in node editing mode.
|
||||
>
|
||||
> 5.Fix the issue where clicking on a node can also trigger node_dragend event.
|
||||
>
|
||||
> 6.Fix that clicking on the canvas and nodes while not in the format brush will also trigger the painter_end event.
|
||||
>
|
||||
> 7.Fixed the issue where the mind map text editing box was not destroyed during node text editing and associated line text editing.
|
||||
|
||||
New:
|
||||
|
||||
> 1.When holding down the Ctrl key, disable the node double-click event.
|
||||
>
|
||||
> 2.Support configuring the behavior when creating new nodes: focusing and entering editing, not focusing, only focusing.
|
||||
>
|
||||
> 3.When searching in read-only mode, add a highlight effect to the currently matched node.
|
||||
>
|
||||
> 4.The default behavior of the mouse scroll wheel is to move the canvas up and down; The default is to scroll forward to enlarge the canvas and zoom back.
|
||||
>
|
||||
> 5.When the mouse scroll wheel behavior is to move the canvas up and down, it supports holding down the Ctrl key to zoom in and out of the canvas.
|
||||
|
||||
Demo:支持配置创建新节点时的行为。
|
||||
|
||||
## 0.9.0
|
||||
|
||||
New:
|
||||
|
||||
@@ -1,6 +1,26 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Changelog</h1>
|
||||
<h2>0.9.1</h2>
|
||||
<p>Fix:</p>
|
||||
<blockquote>
|
||||
<p>1.Fix the issue of exporting images, SVGs, and PDFs with errors when customizing node content.</p>
|
||||
<p>2.Optimize the distribution of node activation events, do not distribute events when the activation node has not changed, and skip intermediate events when distributing multiple events in a short period of time.</p>
|
||||
<p>3.Fix the issue where the edit box and node detach when scrolling the canvas with the mouse while the node is in editing mode.</p>
|
||||
<p>4.Fix the issue of shortcut keys becoming invalid when zooming the canvas with the mouse wheel and then exiting node editing while in node editing mode.</p>
|
||||
<p>5.Fix the issue where clicking on a node can also trigger node_dragend event.</p>
|
||||
<p>6.Fix that clicking on the canvas and nodes while not in the format brush will also trigger the painter_end event.</p>
|
||||
<p>7.Fixed the issue where the mind map text editing box was not destroyed during node text editing and associated line text editing.</p>
|
||||
</blockquote>
|
||||
<p>New:</p>
|
||||
<blockquote>
|
||||
<p>1.When holding down the Ctrl key, disable the node double-click event.</p>
|
||||
<p>2.Support configuring the behavior when creating new nodes: focusing and entering editing, not focusing, only focusing.</p>
|
||||
<p>3.When searching in read-only mode, add a highlight effect to the currently matched node.</p>
|
||||
<p>4.The default behavior of the mouse scroll wheel is to move the canvas up and down; The default is to scroll forward to enlarge the canvas and zoom back.</p>
|
||||
<p>5.When the mouse scroll wheel behavior is to move the canvas up and down, it supports holding down the Ctrl key to zoom in and out of the canvas.</p>
|
||||
</blockquote>
|
||||
<p>Demo:支持配置创建新节点时的行为。</p>
|
||||
<h2>0.9.0</h2>
|
||||
<p>New:</p>
|
||||
<p>1.Support adding summaries to some child nodes of the same node.</p>
|
||||
|
||||
@@ -43,9 +43,9 @@ const mindMap = new MindMap({
|
||||
| watermarkConfig(v0.2.4+) | Object | | Watermark config, Please refer to the table 【Watermark config】 below for detailed configuration | |
|
||||
| textAutoWrapWidth(v0.3.4+) | Number | 500 | Each line of text in the node will wrap automatically when it reaches the width | |
|
||||
| customHandleMousewheel(v0.4.3+) | Function | null | User-defined mouse wheel event processing can pass a function, and the callback parameter is the event object | |
|
||||
| mousewheelAction(v0.4.3+) | String | zoom | The behavior of the mouse wheel, `zoom`(Zoom in and out)、`move`(Move up and down). If `customHandleMousewheel` passes a custom function, this property will not take effect | |
|
||||
| mousewheelAction(v0.4.3+) | String | zoom(v0.9.1+ default is move) | The behavior of the mouse wheel, `zoom`(Zoom in and out)、`move`(Move up and down). If `customHandleMousewheel` passes a custom function, this property will not take effect | |
|
||||
| mousewheelMoveStep(v0.4.3+) | Number | 100 | When the `mousewheelAction` is set to `move`, you can use this attribute to control the step length of the view movement when the mouse scrolls. The unit is `px` | |
|
||||
| mousewheelZoomActionReverse(v0.6.5+) | Boolean | false | When `mousewheelAction` is set to `zoom`, the default scrolling forward is to zoom out, and scrolling backward is to zoom in. If this property is set to true, it will be reversed | |
|
||||
| mousewheelZoomActionReverse(v0.6.5+) | Boolean | false(v0.9.1+ default is true) | When `mousewheelAction` is set to `zoom`, Or when holding down the Ctrl key, the default scrolling forward is to zoom out, and scrolling backward is to zoom in. If this property is set to true, it will be reversed | |
|
||||
| defaultInsertSecondLevelNodeText(v0.4.7+) | String | 二级节点 | Text of the default inserted secondary node | |
|
||||
| defaultInsertBelowSecondLevelNodeText(v0.4.7+) | String | 分支主题 | Text for nodes below the second level inserted by default | |
|
||||
| expandBtnStyle(v0.5.0+) | Object | { color: '#808080', fill: '#fff', fontSize: 13, strokeColor: '#333333' } | Expand the color of the stow button, (The fontSize and strokeColor fields were added in version 0.7.0+to set the text style for displaying the number of nodes when folded) | |
|
||||
@@ -103,6 +103,7 @@ const mindMap = new MindMap({
|
||||
| isDisableDrag(v0.8.1+) | Boolean | false | Is disable dragging the canvas | |
|
||||
| disableTouchZoom(v0.8.1+) | Boolean | false | Prohibit double finger scaling, you can still use the API for scaling, which takes effect on the TouchEvent plugin | |
|
||||
| highlightNodeBoxStyle(v0.9.0+) | Object | { stroke: 'rgb(94, 200, 248)', fill: 'transparent' } | Highlight box style when the mouse moves into the summary to highlight the node it belongs to | |
|
||||
| createNewNodeBehavior(v0.9.1+) | String | default | Behavior when creating a new node. default(By default, newly created nodes will be activated and enter editing mode. If multiple new nodes are created simultaneously, they will only be activated and will not enter editing mode)、notActive(Do not activate newly created nodes)、activeOnly(Only activate newly created nodes and do not enter editing mode) | |
|
||||
|
||||
### Data structure
|
||||
|
||||
|
||||
@@ -164,7 +164,7 @@
|
||||
<tr>
|
||||
<td>mousewheelAction(v0.4.3+)</td>
|
||||
<td>String</td>
|
||||
<td>zoom</td>
|
||||
<td>zoom(v0.9.1+ default is move)</td>
|
||||
<td>The behavior of the mouse wheel, <code>zoom</code>(Zoom in and out)、<code>move</code>(Move up and down). If <code>customHandleMousewheel</code> passes a custom function, this property will not take effect</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
@@ -178,8 +178,8 @@
|
||||
<tr>
|
||||
<td>mousewheelZoomActionReverse(v0.6.5+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>false</td>
|
||||
<td>When <code>mousewheelAction</code> is set to <code>zoom</code>, the default scrolling forward is to zoom out, and scrolling backward is to zoom in. If this property is set to true, it will be reversed</td>
|
||||
<td>false(v0.9.1+ default is true)</td>
|
||||
<td>When <code>mousewheelAction</code> is set to <code>zoom</code>, Or when holding down the Ctrl key, the default scrolling forward is to zoom out, and scrolling backward is to zoom in. If this property is set to true, it will be reversed</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -581,6 +581,13 @@
|
||||
<td>Highlight box style when the mouse moves into the summary to highlight the node it belongs to</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>createNewNodeBehavior(v0.9.1+)</td>
|
||||
<td>String</td>
|
||||
<td>default</td>
|
||||
<td>Behavior when creating a new node. default(By default, newly created nodes will be activated and enter editing mode. If multiple new nodes are created simultaneously, they will only be activated and will not enter editing mode)、notActive(Do not activate newly created nodes)、activeOnly(Only activate newly created nodes and do not enter editing mode)</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>Data structure</h3>
|
||||
|
||||
@@ -253,4 +253,8 @@ Open source is not easy. If this project is helpful to you, you can invite the a
|
||||
<img src="../../../../assets/avatar/moom.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>moom</p>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
|
||||
<img src="../../../../assets/avatar/张扬.png" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>张扬</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -8,17 +8,17 @@
|
||||
</blockquote>
|
||||
<h2>Features</h2>
|
||||
<ul>
|
||||
<li><input type="checkbox" id="checkbox32" checked="true" /><label for="checkbox32">Pluggable architecture, in addition to core functions, other functions are provided as plugins, which can be used as needed to reduce packaging volume</label></li>
|
||||
<li><input type="checkbox" id="checkbox33" checked="true" /><label for="checkbox33">Support logical structure chart, mind map, Organizational chart, directory organization chart, timeline (horizontal and vertical), fishbone chart and other structures</label></li>
|
||||
<li><input type="checkbox" id="checkbox34" checked="true" /><label for="checkbox34">Built-in multiple themes, allowing for highly customizable styles, and supporting registration of new themes</label></li>
|
||||
<li><input type="checkbox" id="checkbox35" checked="true" /><label for="checkbox35">Node content supports text (regular text, rich text), images, icons, hyperlinks, notes, labels, summaries, and math formulas</label></li>
|
||||
<li><input type="checkbox" id="checkbox36" checked="true" /><label for="checkbox36">Nodes support drag and drop (drag and move, freely adjust), multiple node shapes, and fully customize node content using DDM</label></li>
|
||||
<li><input type="checkbox" id="checkbox37" checked="true" /><label for="checkbox37">Support canvas dragging and scaling</label></li>
|
||||
<li><input type="checkbox" id="checkbox38" checked="true" /><label for="checkbox38">Supports two multi node selection methods: mouse button drag selection and Ctrl+left button selection</label></li>
|
||||
<li><input type="checkbox" id="checkbox39" checked="true" /><label for="checkbox39">Supoorts to export as </label><code>json</code>、<code>png</code>、<code>svg</code>、<code>pdf</code>、<code>markdown</code>、<code>xmind</code>, support import from <code>json</code>、<code>xmind</code>、<code>markdown</code></li>
|
||||
<li><input type="checkbox" id="checkbox40" checked="true" /><label for="checkbox40">Support shortcut keys, forward and backward, correlation lines, search and replacement, small maps, watermarks, and scrollbar</label></li>
|
||||
<li><input type="checkbox" id="checkbox41" checked="true" /><label for="checkbox41">Provide rich configurations to meet various scenarios and usage habits</label></li>
|
||||
<li><input type="checkbox" id="checkbox42" checked="true" /><label for="checkbox42">Support collaborative editing</label></li>
|
||||
<li><input type="checkbox" id="checkbox16" checked="true" /><label for="checkbox16">Pluggable architecture, in addition to core functions, other functions are provided as plugins, which can be used as needed to reduce packaging volume</label></li>
|
||||
<li><input type="checkbox" id="checkbox17" checked="true" /><label for="checkbox17">Support logical structure chart, mind map, Organizational chart, directory organization chart, timeline (horizontal and vertical), fishbone chart and other structures</label></li>
|
||||
<li><input type="checkbox" id="checkbox18" checked="true" /><label for="checkbox18">Built-in multiple themes, allowing for highly customizable styles, and supporting registration of new themes</label></li>
|
||||
<li><input type="checkbox" id="checkbox19" checked="true" /><label for="checkbox19">Node content supports text (regular text, rich text), images, icons, hyperlinks, notes, labels, summaries, and math formulas</label></li>
|
||||
<li><input type="checkbox" id="checkbox20" checked="true" /><label for="checkbox20">Nodes support drag and drop (drag and move, freely adjust), multiple node shapes, and fully customize node content using DDM</label></li>
|
||||
<li><input type="checkbox" id="checkbox21" checked="true" /><label for="checkbox21">Support canvas dragging and scaling</label></li>
|
||||
<li><input type="checkbox" id="checkbox22" checked="true" /><label for="checkbox22">Supports two multi node selection methods: mouse button drag selection and Ctrl+left button selection</label></li>
|
||||
<li><input type="checkbox" id="checkbox23" checked="true" /><label for="checkbox23">Supoorts to export as </label><code>json</code>、<code>png</code>、<code>svg</code>、<code>pdf</code>、<code>markdown</code>、<code>xmind</code>, support import from <code>json</code>、<code>xmind</code>、<code>markdown</code></li>
|
||||
<li><input type="checkbox" id="checkbox24" checked="true" /><label for="checkbox24">Support shortcut keys, forward and backward, correlation lines, search and replacement, small maps, watermarks, and scrollbar</label></li>
|
||||
<li><input type="checkbox" id="checkbox25" checked="true" /><label for="checkbox25">Provide rich configurations to meet various scenarios and usage habits</label></li>
|
||||
<li><input type="checkbox" id="checkbox26" checked="true" /><label for="checkbox26">Support collaborative editing</label></li>
|
||||
</ul>
|
||||
<h2>Repository Catalog Introduction</h2>
|
||||
<p>1.<code>simple-mind-map</code></p>
|
||||
@@ -28,16 +28,16 @@ frameworks such as Vue and React, or without a framework.</p>
|
||||
<p>This is an online mind map built using the <code>simple-mind-map</code> library and based
|
||||
on <code>Vue2.x</code> and <code>ElementUI</code>. Features include:</p>
|
||||
<ul>
|
||||
<li><input type="checkbox" id="checkbox43" checked="true" /><label for="checkbox43">Toolbar, which supports inserting and deleting nodes, and editing node</label>
|
||||
<li><input type="checkbox" id="checkbox27" checked="true" /><label for="checkbox27">Toolbar, which supports inserting and deleting nodes, and editing node</label>
|
||||
images, icons, hyperlinks, notes, tags, and summaries</li>
|
||||
<li><input type="checkbox" id="checkbox44" checked="true" /><label for="checkbox44">Sidebar, with panels for basic style settings, node style settings,</label>
|
||||
<li><input type="checkbox" id="checkbox28" checked="true" /><label for="checkbox28">Sidebar, with panels for basic style settings, node style settings,</label>
|
||||
outline, theme selection, and structure selection</li>
|
||||
<li><input type="checkbox" id="checkbox45" checked="true" /><label for="checkbox45">Import and export functionality; data is saved in the browser's local</label>
|
||||
<li><input type="checkbox" id="checkbox29" checked="true" /><label for="checkbox29">Import and export functionality; data is saved in the browser's local</label>
|
||||
storage by default, but it also supports creating, opening, and editing
|
||||
local files on the computer directly</li>
|
||||
<li><input type="checkbox" id="checkbox46" checked="true" /><label for="checkbox46">Right-click menu, which supports operations such as expanding, collapsing,</label>
|
||||
<li><input type="checkbox" id="checkbox30" checked="true" /><label for="checkbox30">Right-click menu, which supports operations such as expanding, collapsing,</label>
|
||||
and organizing layout</li>
|
||||
<li><input type="checkbox" id="checkbox47" checked="true" /><label for="checkbox47">Bottom bar, which supports node and word count statistics, switching</label>
|
||||
<li><input type="checkbox" id="checkbox31" checked="true" /><label for="checkbox31">Bottom bar, which supports node and word count statistics, switching</label>
|
||||
between edit and read-only modes, zooming in and out, and switching to
|
||||
full screen, support mini map</li>
|
||||
</ul>
|
||||
@@ -209,6 +209,10 @@ full screen, support mini map</li>
|
||||
<img src="../../../../assets/avatar/moom.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>moom</p>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
|
||||
<img src="../../../../assets/avatar/张扬.png" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>张扬</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -408,6 +408,22 @@ Remove the data of a node from its parent node's `nodeData.children` list.
|
||||
|
||||
Determine whether there is a hierarchical relationship from the given node instance list.
|
||||
|
||||
#### handleSelfCloseTags(str)
|
||||
|
||||
> v0.9.1+
|
||||
|
||||
- `str`: html string
|
||||
|
||||
Add a closed state to HTML self closing tags, `<div><img src="xxx"></div>` -> `<div><img src="xxx" /></div>`。
|
||||
|
||||
#### checkNodeListIsEqual(list1, list2)
|
||||
|
||||
> v0.9.1+
|
||||
|
||||
- `list1/list2`: Node instance list
|
||||
|
||||
Check if the two node instance lists contain the same nodes.
|
||||
|
||||
## Simulate CSS background in Canvas
|
||||
|
||||
Import:
|
||||
|
||||
@@ -333,6 +333,22 @@ and copying the <code>data</code> of the data object, example:</p>
|
||||
<p>v0.8.1+</p>
|
||||
</blockquote>
|
||||
<p>Determine whether there is a hierarchical relationship from the given node instance list.</p>
|
||||
<h4>handleSelfCloseTags(str)</h4>
|
||||
<blockquote>
|
||||
<p>v0.9.1+</p>
|
||||
</blockquote>
|
||||
<ul>
|
||||
<li><code>str</code>: html string</li>
|
||||
</ul>
|
||||
<p>Add a closed state to HTML self closing tags, <code><div><img src="xxx"></div></code> -> <code><div><img src="xxx" /></div></code>。</p>
|
||||
<h4>checkNodeListIsEqual(list1, list2)</h4>
|
||||
<blockquote>
|
||||
<p>v0.9.1+</p>
|
||||
</blockquote>
|
||||
<ul>
|
||||
<li><code>list1/list2</code>: Node instance list</li>
|
||||
</ul>
|
||||
<p>Check if the two node instance lists contain the same nodes.</p>
|
||||
<h2>Simulate CSS background in Canvas</h2>
|
||||
<p>Import:</p>
|
||||
<pre class="hljs"><code><span class="hljs-keyword">import</span> drawBackgroundImageToCanvas <span class="hljs-keyword">from</span> <span class="hljs-string">'simple-mind-map/src/utils/simulateCSSBackgroundInCanvas'</span>
|
||||
|
||||
@@ -1,5 +1,37 @@
|
||||
# Changelog
|
||||
|
||||
## 0.9.1
|
||||
|
||||
修复:
|
||||
|
||||
> 1.修复自定义节点内容时导出图片、svg、pdf报错的问题。
|
||||
>
|
||||
> 2.优化节点激活事件的派发,激活节点未改变时不派发事件,短时间派发多次事件时跳过中间事件。
|
||||
>
|
||||
> 3.修复节点处于编辑状态时,通过鼠标滚动移动画布后编辑框和节点脱离的问题。
|
||||
>
|
||||
> 4.修复在节点编辑状态中通过鼠标滚轮缩放画布再退出节点编辑后快捷键失效的问题。
|
||||
>
|
||||
> 5.修复点击节点也会触发node_dragend事件的问题。
|
||||
>
|
||||
> 6.修复不在格式刷时点击画布和节点也会触发painter_end事件的问题。
|
||||
>
|
||||
> 7.修复在节点文本编辑中和关联线文本编辑中时销毁思维导图文本编辑框未被销毁的问题。
|
||||
|
||||
新增:
|
||||
|
||||
> 1.按住Ctrl键时禁用节点双击事件。
|
||||
>
|
||||
> 2.支持配置创建新节点时的行为:聚焦且进入编辑、不聚焦、只聚焦。
|
||||
>
|
||||
> 3.只读模式下搜索时给当前匹配到的节点增加高亮效果。
|
||||
>
|
||||
> 4.鼠标滚轮行为默认改为上下移动画布;默认改为向前滚动放大画布,向后缩小。
|
||||
>
|
||||
> 5.在鼠标滚轮行为为上下移动画布时,支持按住Ctrl键进行放大缩小画布。
|
||||
|
||||
Demo:支持配置创建新节点时的行为。
|
||||
|
||||
## 0.9.0
|
||||
|
||||
新增:
|
||||
|
||||
@@ -1,6 +1,26 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Changelog</h1>
|
||||
<h2>0.9.1</h2>
|
||||
<p>修复:</p>
|
||||
<blockquote>
|
||||
<p>1.修复自定义节点内容时导出图片、svg、pdf报错的问题。</p>
|
||||
<p>2.优化节点激活事件的派发,激活节点未改变时不派发事件,短时间派发多次事件时跳过中间事件。</p>
|
||||
<p>3.修复节点处于编辑状态时,通过鼠标滚动移动画布后编辑框和节点脱离的问题。</p>
|
||||
<p>4.修复在节点编辑状态中通过鼠标滚轮缩放画布再退出节点编辑后快捷键失效的问题。</p>
|
||||
<p>5.修复点击节点也会触发node_dragend事件的问题。</p>
|
||||
<p>6.修复不在格式刷时点击画布和节点也会触发painter_end事件的问题。</p>
|
||||
<p>7.修复在节点文本编辑中和关联线文本编辑中时销毁思维导图文本编辑框未被销毁的问题。</p>
|
||||
</blockquote>
|
||||
<p>新增:</p>
|
||||
<blockquote>
|
||||
<p>1.按住Ctrl键时禁用节点双击事件。</p>
|
||||
<p>2.支持配置创建新节点时的行为:聚焦且进入编辑、不聚焦、只聚焦。</p>
|
||||
<p>3.只读模式下搜索时给当前匹配到的节点增加高亮效果。</p>
|
||||
<p>4.鼠标滚轮行为默认改为上下移动画布;默认改为向前滚动放大画布,向后缩小。</p>
|
||||
<p>5.在鼠标滚轮行为为上下移动画布时,支持按住Ctrl键进行放大缩小画布。</p>
|
||||
</blockquote>
|
||||
<p>Demo:支持配置创建新节点时的行为。</p>
|
||||
<h2>0.9.0</h2>
|
||||
<p>新增:</p>
|
||||
<p>1.支持对同一个节点的部分子节点添加概要。</p>
|
||||
|
||||
@@ -43,9 +43,9 @@ const mindMap = new MindMap({
|
||||
| watermarkConfig(v0.2.4+) | Object | | 水印配置,详细配置请参考下方表格【水印配置】 |
|
||||
| textAutoWrapWidth(v0.3.4+) | Number | 500 | 节点内每行文本达到该宽度后自动换行 |
|
||||
| customHandleMousewheel(v0.4.3+) | Function | null | 自定义鼠标滚轮事件处理,可以传一个函数,回调参数为事件对象 |
|
||||
| mousewheelAction(v0.4.3+) | String | zoom | 鼠标滚轮的行为,`zoom`(放大缩小)、`move`(上下移动)。如果`customHandleMousewheel`传了自定义函数,这个属性不生效 |
|
||||
| mousewheelAction(v0.4.3+) | String | zoom(v0.9.1+默认改为move) | 鼠标滚轮的行为,`zoom`(放大缩小)、`move`(上下移动)。如果`customHandleMousewheel`传了自定义函数,这个属性不生效 |
|
||||
| mousewheelMoveStep(v0.4.3+) | Number | 100 | 当`mousewheelAction`设为`move`时,可以通过该属性控制鼠标滚动一下视图移动的步长,单位`px` |
|
||||
| mousewheelZoomActionReverse(v0.6.5+) | Boolean | false | 当mousewheelAction设为zoom时,默认向前滚动是缩小,向后滚动是放大,如果该属性设为true,那么会反过来 |
|
||||
| mousewheelZoomActionReverse(v0.6.5+) | Boolean | false(v0.9.1+默认改为true) | 当mousewheelAction设为zoom时,或者按住Ctrl键时,默认向前滚动是缩小,向后滚动是放大,如果该属性设为true,那么会反过来 |
|
||||
| defaultInsertSecondLevelNodeText(v0.4.7+) | String | 二级节点 | 默认插入的二级节点的文字 |
|
||||
| defaultInsertBelowSecondLevelNodeText(v0.4.7+) | String | 分支主题 | 默认插入的二级以下节点的文字 |
|
||||
| expandBtnStyle(v0.5.0+) | Object | { color: '#808080', fill: '#fff', fontSize: 13, strokeColor: '#333333' } | 展开收起按钮的颜色,(fontSize及strokeColor字段为0.7.0+版本新增的,用于设置收起时显示节点数量的文字样式) |
|
||||
@@ -103,6 +103,7 @@ const mindMap = new MindMap({
|
||||
| isDisableDrag(v0.8.1+) | Boolean | false | 是否禁止拖动画布 |
|
||||
| disableTouchZoom(v0.8.1+) | Boolean | false | 禁止双指缩放,你仍旧可以使用api进行缩放,对TouchEvent插件生效 |
|
||||
| highlightNodeBoxStyle(v0.9.0+) | Object | { stroke: 'rgb(94, 200, 248)', fill: 'transparent' } | 鼠标移入概要高亮所属节点时的高亮框样式 |
|
||||
| createNewNodeBehavior(v0.9.1+) | String | default | 创建新节点时的行为。default(默认会激活新创建的节点,并且进入编辑模式。如果同时创建了多个新节点,那么只会激活而不会进入编辑模式)、notActive(不激活新创建的节点)、activeOnly(只激活新创建的节点,不进入编辑模式) |
|
||||
|
||||
### 数据结构
|
||||
|
||||
|
||||
@@ -144,7 +144,7 @@
|
||||
<tr>
|
||||
<td>mousewheelAction(v0.4.3+)</td>
|
||||
<td>String</td>
|
||||
<td>zoom</td>
|
||||
<td>zoom(v0.9.1+默认改为move)</td>
|
||||
<td>鼠标滚轮的行为,<code>zoom</code>(放大缩小)、<code>move</code>(上下移动)。如果<code>customHandleMousewheel</code>传了自定义函数,这个属性不生效</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -156,8 +156,8 @@
|
||||
<tr>
|
||||
<td>mousewheelZoomActionReverse(v0.6.5+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>false</td>
|
||||
<td>当mousewheelAction设为zoom时,默认向前滚动是缩小,向后滚动是放大,如果该属性设为true,那么会反过来</td>
|
||||
<td>false(v0.9.1+默认改为true)</td>
|
||||
<td>当mousewheelAction设为zoom时,或者按住Ctrl键时,默认向前滚动是缩小,向后滚动是放大,如果该属性设为true,那么会反过来</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>defaultInsertSecondLevelNodeText(v0.4.7+)</td>
|
||||
@@ -501,6 +501,12 @@
|
||||
<td>{ stroke: 'rgb(94, 200, 248)', fill: 'transparent' }</td>
|
||||
<td>鼠标移入概要高亮所属节点时的高亮框样式</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>createNewNodeBehavior(v0.9.1+)</td>
|
||||
<td>String</td>
|
||||
<td>default</td>
|
||||
<td>创建新节点时的行为。default(默认会激活新创建的节点,并且进入编辑模式。如果同时创建了多个新节点,那么只会激活而不会进入编辑模式)、notActive(不激活新创建的节点)、activeOnly(只激活新创建的节点,不进入编辑模式)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>数据结构</h3>
|
||||
|
||||
@@ -82,7 +82,7 @@ mindMap.scrollbar.setScrollBarWrapSize(width, height)
|
||||
然后你需要监听`scrollbar_change`方法来获取滚动条大小和位置数据:
|
||||
|
||||
```js
|
||||
mindMap.('scrollbar_change', this.updateScrollbar)
|
||||
mindMap.on('scrollbar_change', this.updateScrollbar)
|
||||
|
||||
// 根据事件返回的滚动条数据更新滚动条元素:
|
||||
{
|
||||
|
||||
@@ -70,7 +70,7 @@ mindMap.scrollbar.setScrollBarWrapSize(width, height)
|
||||
</code></pre>
|
||||
<p>如果容器大小发生了改变需要再次调用该方法传递改变后的大小。</p>
|
||||
<p>然后你需要监听<code>scrollbar_change</code>方法来获取滚动条大小和位置数据:</p>
|
||||
<pre class="hljs"><code>mindMap.(<span class="hljs-string">'scrollbar_change'</span>, <span class="hljs-built_in">this</span>.updateScrollbar)
|
||||
<pre class="hljs"><code>mindMap.on(<span class="hljs-string">'scrollbar_change'</span>, <span class="hljs-built_in">this</span>.updateScrollbar)
|
||||
|
||||
<span class="hljs-comment">// 根据事件返回的滚动条数据更新滚动条元素:</span>
|
||||
{
|
||||
|
||||
@@ -246,4 +246,8 @@
|
||||
<img src="../../../../assets/avatar/moom.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>moom</p>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
|
||||
<img src="../../../../assets/avatar/张扬.png" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>张扬</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -203,6 +203,10 @@
|
||||
<img src="../../../../assets/avatar/moom.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>moom</p>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
|
||||
<img src="../../../../assets/avatar/张扬.png" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>张扬</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -403,6 +403,22 @@ copyNodeTree({}, node)
|
||||
|
||||
从给定的节点实例列表里判断是否存在上下级关系。
|
||||
|
||||
#### handleSelfCloseTags(str)
|
||||
|
||||
> v0.9.1+
|
||||
|
||||
- `str`:html字符串
|
||||
|
||||
给html自闭合标签添加闭合状态,`<div><img src="xxx"></div>` -> `<div><img src="xxx" /></div>`。
|
||||
|
||||
#### checkNodeListIsEqual(list1, list2)
|
||||
|
||||
> v0.9.1+
|
||||
|
||||
- `list1/list2`:节点实例列表
|
||||
|
||||
检查两个节点实例列表包含的节点是否是一样的。
|
||||
|
||||
## 在canvas中模拟css的背景属性
|
||||
|
||||
引入:
|
||||
|
||||
@@ -328,6 +328,22 @@
|
||||
<p>v0.8.1+</p>
|
||||
</blockquote>
|
||||
<p>从给定的节点实例列表里判断是否存在上下级关系。</p>
|
||||
<h4>handleSelfCloseTags(str)</h4>
|
||||
<blockquote>
|
||||
<p>v0.9.1+</p>
|
||||
</blockquote>
|
||||
<ul>
|
||||
<li><code>str</code>:html字符串</li>
|
||||
</ul>
|
||||
<p>给html自闭合标签添加闭合状态,<code><div><img src="xxx"></div></code> -> <code><div><img src="xxx" /></div></code>。</p>
|
||||
<h4>checkNodeListIsEqual(list1, list2)</h4>
|
||||
<blockquote>
|
||||
<p>v0.9.1+</p>
|
||||
</blockquote>
|
||||
<ul>
|
||||
<li><code>list1/list2</code>:节点实例列表</li>
|
||||
</ul>
|
||||
<p>检查两个节点实例列表包含的节点是否是一样的。</p>
|
||||
<h2>在canvas中模拟css的背景属性</h2>
|
||||
<p>引入:</p>
|
||||
<pre class="hljs"><code><span class="hljs-keyword">import</span> drawBackgroundImageToCanvas <span class="hljs-keyword">from</span> <span class="hljs-string">'simple-mind-map/src/utils/simulateCSSBackgroundInCanvas'</span>
|
||||
|
||||
@@ -753,6 +753,36 @@
|
||||
</el-select>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 配置创建新节点时的行为 -->
|
||||
<div class="row">
|
||||
<div class="rowItem">
|
||||
<span class="name">{{ $t('baseStyle.createNewNodeBehavior') }}</span>
|
||||
<el-select
|
||||
size="mini"
|
||||
style="width: 120px"
|
||||
v-model="config.createNewNodeBehavior"
|
||||
placeholder=""
|
||||
@change="
|
||||
value => {
|
||||
updateOtherConfig('createNewNodeBehavior', value)
|
||||
}
|
||||
"
|
||||
>
|
||||
<el-option
|
||||
:label="$t('baseStyle.default')"
|
||||
value="default"
|
||||
></el-option>
|
||||
<el-option
|
||||
:label="$t('baseStyle.notActive')"
|
||||
value="notActive"
|
||||
></el-option>
|
||||
<el-option
|
||||
:label="$t('baseStyle.activeOnly')"
|
||||
value="activeOnly"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 是否显示滚动条 -->
|
||||
<div class="row">
|
||||
<div class="rowItem">
|
||||
@@ -843,7 +873,8 @@ export default {
|
||||
config: {
|
||||
enableFreeDrag: false,
|
||||
mousewheelAction: 'zoom',
|
||||
mousewheelZoomActionReverse: false
|
||||
mousewheelZoomActionReverse: false,
|
||||
createNewNodeBehavior: 'default'
|
||||
},
|
||||
watermarkConfig: {
|
||||
show: false,
|
||||
@@ -968,7 +999,8 @@ export default {
|
||||
;[
|
||||
'enableFreeDrag',
|
||||
'mousewheelAction',
|
||||
'mousewheelZoomActionReverse'
|
||||
'mousewheelZoomActionReverse',
|
||||
'createNewNodeBehavior'
|
||||
].forEach(key => {
|
||||
this.config[key] = this.mindMap.getConfig(key)
|
||||
})
|
||||
@@ -979,9 +1011,7 @@ export default {
|
||||
this.enableNodeRichText = this.localConfig.openNodeRichText
|
||||
this.mousewheelAction = this.localConfig.mousewheelAction
|
||||
this.mousewheelZoomActionReverse = this.localConfig.mousewheelZoomActionReverse
|
||||
;[
|
||||
'isShowScrollbar'
|
||||
].forEach(key => {
|
||||
;['isShowScrollbar'].forEach(key => {
|
||||
this.localConfigs[key] = this.localConfig[key]
|
||||
})
|
||||
},
|
||||
|
||||
@@ -188,6 +188,7 @@ export default {
|
||||
this.$bus.$off('node_tree_render_end', this.handleHideLoading)
|
||||
this.$bus.$off('showLoading', this.handleShowLoading)
|
||||
window.removeEventListener('resize', this.handleResize)
|
||||
this.mindMap.destroy()
|
||||
},
|
||||
methods: {
|
||||
handleStartTextEdit() {
|
||||
@@ -317,7 +318,17 @@ export default {
|
||||
type: 'warning'
|
||||
}
|
||||
)
|
||||
}
|
||||
},
|
||||
errorHandler: (code, err) => {
|
||||
console.error(err)
|
||||
switch (code) {
|
||||
case 'export_error':
|
||||
this.$message.error('导出失败')
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
},
|
||||
// isUseCustomNodeContent: true,
|
||||
// 示例1:组件里用到了router、store、i18n等实例化vue组件时需要用到的东西
|
||||
// customCreateNodeContent: (node) => {
|
||||
@@ -344,7 +355,7 @@ export default {
|
||||
// return comp.$el
|
||||
// },
|
||||
// 示例3:普通元素
|
||||
// customCreateNodeContent: (node) => {
|
||||
// customCreateNodeContent: node => {
|
||||
// let el = document.createElement('div')
|
||||
// el.style.cssText = `
|
||||
// width: 203px;
|
||||
@@ -357,9 +368,12 @@ export default {
|
||||
// justify-content: center;
|
||||
// align-items: center;
|
||||
// `
|
||||
// el.innerHTML = node.nodeData.data.text
|
||||
// el.innerHTML = `
|
||||
// ${node.nodeData.data.text}
|
||||
// <img crossOrigin="anonymous" src="/img/cactus.jpg" />
|
||||
// `
|
||||
// return el
|
||||
// },
|
||||
// }
|
||||
})
|
||||
if (this.openNodeRichText) this.addRichTextPlugin()
|
||||
this.mindMap.keyCommand.addShortcut('Control+s', () => {
|
||||
|
||||
@@ -42,11 +42,11 @@ export default {
|
||||
dataList: [
|
||||
{
|
||||
icon: 'iconstar',
|
||||
value: 'Github star数量1000+'
|
||||
value: 'Github star数量2000+'
|
||||
},
|
||||
{
|
||||
icon: 'iconfork',
|
||||
value: 'Github fork数量200+'
|
||||
value: 'Github fork数量250+'
|
||||
},
|
||||
{
|
||||
icon: 'iconxiazai',
|
||||
@@ -54,7 +54,7 @@ export default {
|
||||
},
|
||||
{
|
||||
icon: 'iconteamwork',
|
||||
value: '代码贡献者12+'
|
||||
value: '代码贡献者14+'
|
||||
}
|
||||
],
|
||||
functionList: [
|
||||
|
||||
@@ -20,36 +20,22 @@ const store = new Vuex.Store({
|
||||
isShowScrollbar: false
|
||||
},
|
||||
activeSidebar: '', // 当前显示的侧边栏
|
||||
isDark: false,// 是否是暗黑模式
|
||||
isOutlineEdit: false,// 是否是大纲编辑模式
|
||||
isReadonly: false// 是否只读
|
||||
isDark: false, // 是否是暗黑模式
|
||||
isOutlineEdit: false, // 是否是大纲编辑模式
|
||||
isReadonly: false // 是否只读
|
||||
},
|
||||
mutations: {
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-10 14:50:01
|
||||
* @Desc: 设置思维导图数据
|
||||
*/
|
||||
// 设置思维导图数据
|
||||
setMindMapData(state, data) {
|
||||
state.mindMapData = data
|
||||
},
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林
|
||||
* @Date: 2022-09-24 13:55:38
|
||||
* @Desc: 设置操作本地文件标志位
|
||||
*/
|
||||
// 设置操作本地文件标志位
|
||||
setIsHandleLocalFile(state, data) {
|
||||
state.isHandleLocalFile = data
|
||||
},
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2022-11-14 18:42:47
|
||||
* @Desc: 设置本地配置
|
||||
*/
|
||||
// 设置本地配置
|
||||
setLocalConfig(state, data) {
|
||||
state.localConfig = {
|
||||
...state.localConfig,
|
||||
@@ -58,12 +44,7 @@ const store = new Vuex.Store({
|
||||
storeLocalConfig(state.localConfig)
|
||||
},
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2022-11-15 19:25:26
|
||||
* @Desc: 设置当前显示的侧边栏
|
||||
*/
|
||||
// 设置当前显示的侧边栏
|
||||
setActiveSidebar(state, data) {
|
||||
state.activeSidebar = data
|
||||
},
|
||||
@@ -81,14 +62,10 @@ const store = new Vuex.Store({
|
||||
// 设置是否只读
|
||||
setIsReadonly(state, data) {
|
||||
state.isReadonly = data
|
||||
},
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-10 14:50:40
|
||||
* @Desc: 设置初始思维导图数据
|
||||
*/
|
||||
// 设置初始思维导图数据
|
||||
getUserMindMapData(ctx) {
|
||||
try {
|
||||
let { data } = {
|
||||
|
||||
Reference in New Issue
Block a user