diff --git a/simple-mind-map/.eslintrc.js b/simple-mind-map/.eslintrc.js new file mode 100644 index 00000000..8c033a6f --- /dev/null +++ b/simple-mind-map/.eslintrc.js @@ -0,0 +1,17 @@ +module.exports = { + "env": { + "browser": true, + "es2021": true + }, + "extends": "eslint:recommended", + "overrides": [ + ], + "parserOptions": { + "parser": 'babel-eslint', + "ecmaVersion": 12, + "sourceType": "module", + "allowImportExportEverywhere": true + }, + "rules": { + } +} diff --git a/simple-mind-map/.prettierignore b/simple-mind-map/.prettierignore new file mode 100644 index 00000000..d2ce4a3c --- /dev/null +++ b/simple-mind-map/.prettierignore @@ -0,0 +1,10 @@ +src/assets +*/.DS_Store +dist +example +node_modules +*.json +*.md +.eslintrc.js +.prettierignore +.prettierrc \ No newline at end of file diff --git a/simple-mind-map/.prettierrc b/simple-mind-map/.prettierrc new file mode 100644 index 00000000..ef93d948 --- /dev/null +++ b/simple-mind-map/.prettierrc @@ -0,0 +1,5 @@ +semi: false +singleQuote: true +printWidth: 80 +trailingComma: 'none' +arrowParens: 'avoid' diff --git a/simple-mind-map/index.js b/simple-mind-map/index.js index c481265f..0b664aa0 100644 --- a/simple-mind-map/index.js +++ b/simple-mind-map/index.js @@ -10,45 +10,41 @@ import BatchExecution from './src/BatchExecution' import Export from './src/Export' import Select from './src/Select' import Drag from './src/Drag' -import MiniMap from './src/MiniMap'; -import { - layoutValueList -} from './src/utils/constant' -import { - SVG -} from '@svgdotjs/svg.js' +import MiniMap from './src/MiniMap' +import { layoutValueList } from './src/utils/constant' +import { SVG } from '@svgdotjs/svg.js' import xmind from './src/parse/xmind' -import { simpleDeepClone } from './src/utils'; +import { simpleDeepClone } from './src/utils' // 默认选项配置 const defaultOpt = { - // 是否只读 - readonly: false, - // 布局 - layout: 'logicalStructure', - // 主题 - theme: 'default', // 内置主题:default(默认主题) - // 主题配置,会和所选择的主题进行合并 - themeConfig: {}, - // 放大缩小的增量比例 - scaleRatio: 0.1, - // 最多显示几个标签 - maxTag: 5, - // 导出图片时的内边距 - exportPadding: 20, - // 展开收缩按钮尺寸 - expandBtnSize: 20, - // 节点里图片和文字的间距 - imgTextMargin: 5, - // 节点里各种文字信息的间距,如图标和文字的间距 - textContentMargin: 2, - // 多选节点时鼠标移动到边缘时的画布移动偏移量 - selectTranslateStep: 3, - // 多选节点时鼠标移动距边缘多少距离时开始偏移 - selectTranslateLimit: 20, - // 自定义节点备注内容显示 - customNoteContentShow: null - /* + // 是否只读 + readonly: false, + // 布局 + layout: 'logicalStructure', + // 主题 + theme: 'default', // 内置主题:default(默认主题) + // 主题配置,会和所选择的主题进行合并 + themeConfig: {}, + // 放大缩小的增量比例 + scaleRatio: 0.1, + // 最多显示几个标签 + maxTag: 5, + // 导出图片时的内边距 + exportPadding: 20, + // 展开收缩按钮尺寸 + expandBtnSize: 20, + // 节点里图片和文字的间距 + imgTextMargin: 5, + // 节点里各种文字信息的间距,如图标和文字的间距 + textContentMargin: 2, + // 多选节点时鼠标移动到边缘时的画布移动偏移量 + selectTranslateStep: 3, + // 多选节点时鼠标移动距边缘多少距离时开始偏移 + selectTranslateLimit: 20, + // 自定义节点备注内容显示 + customNoteContentShow: null + /* { show(){}, hide(){} @@ -56,378 +52,378 @@ const defaultOpt = { */ } -/** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-06 11:18:47 - * @Desc: 思维导图 +/** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-06 11:18:47 + * @Desc: 思维导图 */ class MindMap { - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-06 11:19:01 - * @Desc: 构造函数 - */ - constructor(opt = {}) { - // 合并选项 - this.opt = this.handleOpt(merge(defaultOpt, opt)) + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-06 11:19:01 + * @Desc: 构造函数 + */ + constructor(opt = {}) { + // 合并选项 + this.opt = this.handleOpt(merge(defaultOpt, opt)) - // 容器元素 - this.el = this.opt.el - this.elRect = this.el.getBoundingClientRect() + // 容器元素 + this.el = this.opt.el + this.elRect = this.el.getBoundingClientRect() - // 画布宽高 - this.width = this.elRect.width - this.height = this.elRect.height + // 画布宽高 + this.width = this.elRect.width + this.height = this.elRect.height - // 画布 - this.svg = SVG().addTo(this.el).size(this.width, this.height) - this.draw = this.svg.group() + // 画布 + this.svg = SVG().addTo(this.el).size(this.width, this.height) + this.draw = this.svg.group() - // 节点id - this.uid = 0 + // 节点id + this.uid = 0 - // 初始化主题 - this.initTheme() + // 初始化主题 + this.initTheme() - // 事件类 - this.event = new Event({ - mindMap: this - }) + // 事件类 + this.event = new Event({ + mindMap: this + }) - // 按键类 - this.keyCommand = new KeyCommand({ - mindMap: this - }) + // 按键类 + this.keyCommand = new KeyCommand({ + mindMap: this + }) - // 命令类 - this.command = new Command({ - mindMap: this - }) + // 命令类 + this.command = new Command({ + mindMap: this + }) - // 渲染类 - this.renderer = new Render({ - mindMap: this - }) + // 渲染类 + this.renderer = new Render({ + mindMap: this + }) - // 视图操作类 - this.view = new View({ - mindMap: this, - draw: this.draw - }) + // 视图操作类 + this.view = new View({ + mindMap: this, + draw: this.draw + }) - // 小地图类 - this.miniMap = new MiniMap({ - mindMap: this - }) + // 小地图类 + this.miniMap = new MiniMap({ + mindMap: this + }) - // 导出类 - this.doExport = new Export({ - mindMap: this - }) + // 导出类 + this.doExport = new Export({ + mindMap: this + }) - // 选择类 - this.select = new Select({ - mindMap: this - }) + // 选择类 + this.select = new Select({ + mindMap: this + }) - // 拖动类 - this.drag = new Drag({ - mindMap: this - }) + // 拖动类 + this.drag = new Drag({ + mindMap: this + }) - // 批量执行类 - this.batchExecution = new BatchExecution() + // 批量执行类 + this.batchExecution = new BatchExecution() - // 初始渲染 - this.reRender() - setTimeout(() => { - this.command.addHistory() - }, 0) + // 初始渲染 + this.reRender() + setTimeout(() => { + this.command.addHistory() + }, 0) + } + + /** + * @Author: 王林 + * @Date: 2021-07-01 22:15:22 + * @Desc: 配置参数处理 + */ + handleOpt(opt) { + // 检查布局配置 + if (!layoutValueList.includes(opt.layout)) { + opt.layout = 'logicalStructure' } + // 检查主题配置 + opt.theme = opt.theme && theme[opt.theme] ? opt.theme : 'default' + return opt + } - /** - * @Author: 王林 - * @Date: 2021-07-01 22:15:22 - * @Desc: 配置参数处理 - */ - handleOpt(opt) { - // 检查布局配置 - if (!layoutValueList.includes(opt.layout)) { - opt.layout = 'logicalStructure' - } - // 检查主题配置 - opt.theme = opt.theme && theme[opt.theme] ? opt.theme : 'default' - return opt - } + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-06 18:47:29 + * @Desc: 渲染,部分渲染 + */ + render() { + this.batchExecution.push('render', () => { + this.initTheme() + this.renderer.reRender = false + this.renderer.render() + }) + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-06 18:47:29 - * @Desc: 渲染,部分渲染 - */ - render() { - this.batchExecution.push('render', () => { - this.initTheme() - this.renderer.reRender = false - this.renderer.render() - }) - } + /** + * @Author: 王林 + * @Date: 2021-07-08 22:05:11 + * @Desc: 重新渲染 + */ + reRender() { + this.batchExecution.push('render', () => { + this.draw.clear() + this.initTheme() + this.renderer.reRender = true + this.renderer.render() + }) + } - /** - * @Author: 王林 - * @Date: 2021-07-08 22:05:11 - * @Desc: 重新渲染 - */ - reRender() { - this.batchExecution.push('render', () => { - this.draw.clear() - this.initTheme() - this.renderer.reRender = true - this.renderer.render() - }) - } + /** + * @Author: 王林 + * @Date: 2021-07-11 21:16:52 + * @Desc: 容器尺寸变化,调整尺寸 + */ + resize() { + this.elRect = this.el.getBoundingClientRect() + this.width = this.elRect.width + this.height = this.elRect.height + this.svg.size(this.width, this.height) + } - /** - * @Author: 王林 - * @Date: 2021-07-11 21:16:52 - * @Desc: 容器尺寸变化,调整尺寸 - */ - resize() { - this.elRect = this.el.getBoundingClientRect() - this.width = this.elRect.width - this.height = this.elRect.height - this.svg.size(this.width, this.height) - } + /** + * @Author: 王林 + * @Date: 2021-04-24 13:25:50 + * @Desc: 监听事件 + */ + on(event, fn) { + this.event.on(event, fn) + } - /** - * @Author: 王林 - * @Date: 2021-04-24 13:25:50 - * @Desc: 监听事件 - */ - on(event, fn) { - this.event.on(event, fn) - } + /** + * @Author: 王林 + * @Date: 2021-04-24 13:51:35 + * @Desc: 触发事件 + */ + emit(event, ...args) { + this.event.emit(event, ...args) + } - /** - * @Author: 王林 - * @Date: 2021-04-24 13:51:35 - * @Desc: 触发事件 - */ - emit(event, ...args) { - this.event.emit(event, ...args) - } + /** + * @Author: 王林 + * @Date: 2021-04-24 13:53:54 + * @Desc: 解绑事件 + */ + off(event, fn) { + this.event.off(event, fn) + } - /** - * @Author: 王林 - * @Date: 2021-04-24 13:53:54 - * @Desc: 解绑事件 - */ - off(event, fn) { - this.event.off(event, fn) - } + /** + * @Author: 王林 + * @Date: 2021-05-05 13:32:43 + * @Desc: 设置主题 + */ + initTheme() { + // 合并主题配置 + this.themeConfig = merge(theme[this.opt.theme], this.opt.themeConfig) + // 设置背景样式 + Style.setBackgroundStyle(this.el, this.themeConfig) + } - /** - * @Author: 王林 - * @Date: 2021-05-05 13:32:43 - * @Desc: 设置主题 - */ - initTheme() { - // 合并主题配置 - this.themeConfig = merge(theme[this.opt.theme], this.opt.themeConfig) - // 设置背景样式 - Style.setBackgroundStyle(this.el, this.themeConfig) - } + /** + * @Author: 王林 + * @Date: 2021-05-05 13:52:08 + * @Desc: 设置主题 + */ + setTheme(theme) { + this.renderer.clearAllActive() + this.opt.theme = theme + this.reRender() + } - /** - * @Author: 王林 - * @Date: 2021-05-05 13:52:08 - * @Desc: 设置主题 - */ - setTheme(theme) { - this.renderer.clearAllActive() - this.opt.theme = theme - this.reRender() - } + /** + * @Author: 王林 + * @Date: 2021-06-25 23:52:37 + * @Desc: 获取当前主题 + */ + getTheme() { + return this.opt.theme + } - /** - * @Author: 王林 - * @Date: 2021-06-25 23:52:37 - * @Desc: 获取当前主题 - */ - getTheme() { - return this.opt.theme - } + /** + * @Author: 王林 + * @Date: 2021-05-05 13:50:17 + * @Desc: 设置主题配置 + */ + setThemeConfig(config) { + this.opt.themeConfig = config + this.reRender() + } - /** - * @Author: 王林 - * @Date: 2021-05-05 13:50:17 - * @Desc: 设置主题配置 - */ - setThemeConfig(config) { - this.opt.themeConfig = config - this.reRender() - } + /** + * @Author: 王林 + * @Date: 2021-08-01 10:38:34 + * @Desc: 获取自定义主题配置 + */ + getCustomThemeConfig() { + return this.opt.themeConfig + } - /** - * @Author: 王林 - * @Date: 2021-08-01 10:38:34 - * @Desc: 获取自定义主题配置 - */ - getCustomThemeConfig() { - return this.opt.themeConfig - } + /** + * @Author: 王林 + * @Date: 2021-05-05 14:01:29 + * @Desc: 获取某个主题配置值 + */ + getThemeConfig(prop) { + return prop === undefined ? this.themeConfig : this.themeConfig[prop] + } - /** - * @Author: 王林 - * @Date: 2021-05-05 14:01:29 - * @Desc: 获取某个主题配置值 - */ - getThemeConfig(prop) { - return prop === undefined ? this.themeConfig : this.themeConfig[prop] - } + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-07-13 16:17:06 + * @Desc: 获取当前布局结构 + */ + getLayout() { + return this.opt.layout + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-07-13 16:17:06 - * @Desc: 获取当前布局结构 - */ - getLayout() { - return this.opt.layout + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-07-13 16:17:33 + * @Desc: 设置布局结构 + */ + setLayout(layout) { + // 检查布局配置 + if (!layoutValueList.includes(layout)) { + layout = 'logicalStructure' } + this.opt.layout = layout + this.renderer.setLayout() + this.render() + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-07-13 16:17:33 - * @Desc: 设置布局结构 - */ - setLayout(layout) { - // 检查布局配置 - if (!layoutValueList.includes(layout)) { - layout = 'logicalStructure' - } - this.opt.layout = layout - this.renderer.setLayout() - this.render() - } + /** + * @Author: 王林 + * @Date: 2021-05-04 13:01:00 + * @Desc: 执行命令 + */ + execCommand(...args) { + this.command.exec(...args) + } - /** - * @Author: 王林 - * @Date: 2021-05-04 13:01:00 - * @Desc: 执行命令 - */ - execCommand(...args) { - this.command.exec(...args) - } + /** + * @Author: 王林 + * @Date: 2021-08-03 22:58:12 + * @Desc: 动态设置思维导图数据,纯节点数据 + */ + setData(data) { + this.execCommand('CLEAR_ACTIVE_NODE') + this.command.clearHistory() + this.renderer.renderTree = data + this.reRender() + } - /** - * @Author: 王林 - * @Date: 2021-08-03 22:58:12 - * @Desc: 动态设置思维导图数据,纯节点数据 - */ - setData(data) { - this.execCommand('CLEAR_ACTIVE_NODE') - this.command.clearHistory() - this.renderer.renderTree = data - this.reRender() + /** + * javascript comment + * @Author: 王林25 + * @Date: 2022-09-21 16:39:13 + * @Desc: 动态设置思维导图数据,包括节点数据、布局、主题、视图 + */ + setFullData(data) { + if (data.root) { + this.setData(data.root) } + if (data.layout) { + this.setLayout(data.layout) + } + if (data.theme) { + if (data.theme.template) { + this.setTheme(data.theme.template) + } + if (data.theme.config) { + this.setThemeConfig(data.theme.config) + } + } + if (data.view) { + this.view.setTransformData(data.view) + } + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2022-09-21 16:39:13 - * @Desc: 动态设置思维导图数据,包括节点数据、布局、主题、视图 - */ - setFullData(data) { - if (data.root) { - this.setData(data.root) - } - if (data.layout) { - this.setLayout(data.layout) - } - if (data.theme) { - if (data.theme.template) { - this.setTheme(data.theme.template) - } - if (data.theme.config) { - this.setThemeConfig(data.theme.config) - } - } - if (data.view) { - this.view.setTransformData(data.view) - } + /** + * javascript comment + * @Author: 王林 + * @Date: 2022-09-24 14:42:07 + * @Desc: 获取思维导图数据,节点树、主题、布局等 + */ + getData(withConfig) { + let nodeData = this.command.getCopyData() + let data = {} + if (withConfig) { + data = { + layout: this.getLayout(), + root: nodeData, + theme: { + template: this.getTheme(), + config: this.getCustomThemeConfig() + }, + view: this.view.getTransformData() + } + } else { + data = nodeData } + return simpleDeepClone(data) + } - /** - * javascript comment - * @Author: 王林 - * @Date: 2022-09-24 14:42:07 - * @Desc: 获取思维导图数据,节点树、主题、布局等 - */ - getData(withConfig) { - let nodeData = this.command.getCopyData() - let data = {} - if (withConfig) { - data = { - layout: this.getLayout(), - root: nodeData, - theme: { - template: this.getTheme(), - config: this.getCustomThemeConfig() - }, - view: this.view.getTransformData() - } - } else { - data = nodeData - } - return simpleDeepClone(data) - } + /** + * @Author: 王林 + * @Date: 2021-07-01 22:06:38 + * @Desc: 导出 + */ + async export(...args) { + let result = await this.doExport.export(...args) + return result + } - /** - * @Author: 王林 - * @Date: 2021-07-01 22:06:38 - * @Desc: 导出 - */ - async export(...args) { - let result = await this.doExport.export(...args) - return result + /** + * @Author: 王林 + * @Date: 2021-07-11 09:20:03 + * @Desc: 转换位置 + */ + toPos(x, y) { + return { + x: x - this.elRect.left, + y: y - this.elRect.top } + } - /** - * @Author: 王林 - * @Date: 2021-07-11 09:20:03 - * @Desc: 转换位置 - */ - toPos(x, y) { - return { - x: x - this.elRect.left, - y: y - this.elRect.top - } + /** + * javascript comment + * @Author: 王林25 + * @Date: 2022-06-08 14:12:38 + * @Desc: 设置只读模式、编辑模式 + */ + setMode(mode) { + if (!['readonly', 'edit'].includes(mode)) { + return } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2022-06-08 14:12:38 - * @Desc: 设置只读模式、编辑模式 - */ - setMode(mode) { - if (!['readonly', 'edit'].includes(mode)) { - return - } - this.opt.readonly = mode === 'readonly' - if (this.opt.readonly) { - // 取消当前激活的元素 - this.renderer.clearAllActive() - } - this.emit('mode_change', mode) + this.opt.readonly = mode === 'readonly' + if (this.opt.readonly) { + // 取消当前激活的元素 + this.renderer.clearAllActive() } + this.emit('mode_change', mode) + } } MindMap.xmind = xmind -export default MindMap \ No newline at end of file +export default MindMap diff --git a/simple-mind-map/package.json b/simple-mind-map/package.json index a11e2561..ac77b230 100644 --- a/simple-mind-map/package.json +++ b/simple-mind-map/package.json @@ -17,7 +17,10 @@ "type": "git", "url": "https://github.com/wanglin2/mind-map" }, - "scripts": {}, + "scripts": { + "lint": "eslint src/", + "format": "prettier --write ." + }, "module": "index.js", "main": "./dist/simpleMindMap.umd.min.js", "dependencies": { @@ -35,5 +38,9 @@ "mind-map", "mindMap", "MindMap" - ] + ], + "devDependencies": { + "eslint": "^8.25.0", + "prettier": "^2.7.1" + } } diff --git a/simple-mind-map/src/BatchExecution.js b/simple-mind-map/src/BatchExecution.js index 9db557d1..6ab02019 100644 --- a/simple-mind-map/src/BatchExecution.js +++ b/simple-mind-map/src/BatchExecution.js @@ -1,85 +1,85 @@ -/** - * @Author: 王林 - * @Date: 2021-06-27 13:16:23 - * @Desc: 在下一个事件循环里执行任务 +/** + * @Author: 王林 + * @Date: 2021-06-27 13:16:23 + * @Desc: 在下一个事件循环里执行任务 */ const nextTick = function (fn, ctx) { - let pending = false - let timerFunc = null - let handle = () => { - pending = false - ctx ? fn.call(ctx) : fn() - } - // 支持MutationObserver接口的话使用MutationObserver - if (typeof MutationObserver !== 'undefined') { - let counter = 1 - let observer = new MutationObserver(handle) - let textNode = document.createTextNode(counter) - observer.observe(textNode, { - characterData: true// 设为 true 表示监视指定目标节点或子节点树中节点所包含的字符数据的变化 - }) - timerFunc = function () { - counter = (counter + 1) % 2// counter会在0和1两者循环变化 - textNode.data = counter// 节点变化会触发回调handle, - } - } else {// 否则使用定时器 - timerFunc = setTimeout - } - return function (cb, ctx) { - if (pending) return - pending = true - timerFunc(handle, 0) + let pending = false + let timerFunc = null + let handle = () => { + pending = false + ctx ? fn.call(ctx) : fn() + } + // 支持MutationObserver接口的话使用MutationObserver + if (typeof MutationObserver !== 'undefined') { + let counter = 1 + let observer = new MutationObserver(handle) + let textNode = document.createTextNode(counter) + observer.observe(textNode, { + characterData: true // 设为 true 表示监视指定目标节点或子节点树中节点所包含的字符数据的变化 + }) + timerFunc = function () { + counter = (counter + 1) % 2 // counter会在0和1两者循环变化 + textNode.data = counter // 节点变化会触发回调handle, } + } else { + // 否则使用定时器 + timerFunc = setTimeout + } + return function () { + if (pending) return + pending = true + timerFunc(handle, 0) + } } - -/** - * @Author: 王林 - * @Date: 2021-06-26 22:40:52 - * @Desc: 批量执行 +/** + * @Author: 王林 + * @Date: 2021-06-26 22:40:52 + * @Desc: 批量执行 */ class BatchExecution { - /** - * @Author: 王林 - * @Date: 2021-06-26 22:41:41 - * @Desc: 构造函数 - */ - constructor() { - this.has = {} - this.queue = [] - this.nextTick = nextTick(this.flush, this) - } + /** + * @Author: 王林 + * @Date: 2021-06-26 22:41:41 + * @Desc: 构造函数 + */ + constructor() { + this.has = {} + this.queue = [] + this.nextTick = nextTick(this.flush, this) + } - /** - * @Author: 王林 - * @Date: 2021-06-27 12:54:04 - * @Desc: 添加任务 - */ - push(name, fn) { - if (this.has[name]) { - return; - } - this.has[name] = true - this.queue.push({ - name, - fn - }) - this.nextTick() + /** + * @Author: 王林 + * @Date: 2021-06-27 12:54:04 + * @Desc: 添加任务 + */ + push(name, fn) { + if (this.has[name]) { + return } + this.has[name] = true + this.queue.push({ + name, + fn + }) + this.nextTick() + } - /** - * @Author: 王林 - * @Date: 2021-06-27 13:09:24 - * @Desc: 执行队列 - */ - flush() { - let fns = this.queue.slice(0) - this.queue = [] - fns.forEach(({ name, fn }) => { - this.has[name] = false - fn() - }) - } + /** + * @Author: 王林 + * @Date: 2021-06-27 13:09:24 + * @Desc: 执行队列 + */ + flush() { + let fns = this.queue.slice(0) + this.queue = [] + fns.forEach(({ name, fn }) => { + this.has[name] = false + fn() + }) + } } -export default BatchExecution \ No newline at end of file +export default BatchExecution diff --git a/simple-mind-map/src/Command.js b/simple-mind-map/src/Command.js index 6ebd846e..c0ca82f6 100644 --- a/simple-mind-map/src/Command.js +++ b/simple-mind-map/src/Command.js @@ -1,152 +1,160 @@ -import { copyRenderTree, simpleDeepClone } from './utils'; +import { copyRenderTree, simpleDeepClone } from './utils' -/** - * @Author: 王林 - * @Date: 2021-05-04 13:10:06 - * @Desc: 命令类 +/** + * @Author: 王林 + * @Date: 2021-05-04 13:10:06 + * @Desc: 命令类 */ class Command { - /** - * @Author: 王林 - * @Date: 2021-05-04 13:10:24 - * @Desc: 构造函数 - */ - constructor(opt = {}) { - this.opt = opt - this.mindMap = opt.mindMap - this.commands = {} - this.history = [] - this.activeHistoryIndex = 0 - // 注册快捷键 - this.registerShortcutKeys() - } + /** + * @Author: 王林 + * @Date: 2021-05-04 13:10:24 + * @Desc: 构造函数 + */ + constructor(opt = {}) { + this.opt = opt + this.mindMap = opt.mindMap + this.commands = {} + this.history = [] + this.activeHistoryIndex = 0 + // 注册快捷键 + this.registerShortcutKeys() + } - /** - * @Author: 王林 - * @Date: 2021-08-03 23:06:55 - * @Desc: 清空历史数据 - */ - clearHistory() { - this.history = [] - this.activeHistoryIndex = 0 - this.mindMap.emit('back_forward', 0, 0) - } + /** + * @Author: 王林 + * @Date: 2021-08-03 23:06:55 + * @Desc: 清空历史数据 + */ + clearHistory() { + this.history = [] + this.activeHistoryIndex = 0 + this.mindMap.emit('back_forward', 0, 0) + } - /** - * @Author: 王林 - * @Date: 2021-08-02 23:23:19 - * @Desc: 注册快捷键 - */ - registerShortcutKeys() { - this.mindMap.keyCommand.addShortcut('Control+z', () => { - this.mindMap.execCommand('BACK') - }) - this.mindMap.keyCommand.addShortcut('Control+y', () => { - this.mindMap.execCommand('FORWARD') - }) - } + /** + * @Author: 王林 + * @Date: 2021-08-02 23:23:19 + * @Desc: 注册快捷键 + */ + registerShortcutKeys() { + this.mindMap.keyCommand.addShortcut('Control+z', () => { + this.mindMap.execCommand('BACK') + }) + this.mindMap.keyCommand.addShortcut('Control+y', () => { + this.mindMap.execCommand('FORWARD') + }) + } - /** - * @Author: 王林 - * @Date: 2021-05-04 13:12:30 - * @Desc: 执行命令 - */ - exec(name, ...args) { - if (this.commands[name]) { - this.commands[name].forEach((fn) => { - fn(...args) - }) - if (name === 'BACK' || name === 'FORWARD') { - return; - } - this.addHistory() - } + /** + * @Author: 王林 + * @Date: 2021-05-04 13:12:30 + * @Desc: 执行命令 + */ + exec(name, ...args) { + if (this.commands[name]) { + this.commands[name].forEach(fn => { + fn(...args) + }) + if (name === 'BACK' || name === 'FORWARD') { + return + } + this.addHistory() } + } - /** - * @Author: 王林 - * @Date: 2021-05-04 13:13:01 - * @Desc: 添加命令 - */ - add(name, fn) { - if (this.commands[name]) { - this.commands[name].push(fn) - } else { - this.commands[name] = [fn] - } + /** + * @Author: 王林 + * @Date: 2021-05-04 13:13:01 + * @Desc: 添加命令 + */ + add(name, fn) { + if (this.commands[name]) { + this.commands[name].push(fn) + } else { + this.commands[name] = [fn] } + } - /** - * @Author: 王林 - * @Date: 2021-07-15 23:02:41 - * @Desc: 移除命令 - */ - remove(name, fn) { - if (!this.commands[name]) { - return - } - if (!fn) { - this.commands[name] = [] - delete this.commands[name] - } else { - let index = this.commands[name].find((item) => { - return item === fn; - }) - if (index !== -1) { - this.commands[name].splice(index, 1) - } - } + /** + * @Author: 王林 + * @Date: 2021-07-15 23:02:41 + * @Desc: 移除命令 + */ + remove(name, fn) { + if (!this.commands[name]) { + return } + if (!fn) { + this.commands[name] = [] + delete this.commands[name] + } else { + let index = this.commands[name].find(item => { + return item === fn + }) + if (index !== -1) { + this.commands[name].splice(index, 1) + } + } + } - /** - * @Author: 王林 - * @Date: 2021-05-04 14:35:43 - * @Desc: 添加回退数据 - */ - addHistory() { - let data = this.getCopyData() - this.history.push(simpleDeepClone(data)) - this.activeHistoryIndex = this.history.length - 1 - this.mindMap.emit('data_change', data) - this.mindMap.emit('back_forward', this.activeHistoryIndex, this.history.length) - } + /** + * @Author: 王林 + * @Date: 2021-05-04 14:35:43 + * @Desc: 添加回退数据 + */ + addHistory() { + let data = this.getCopyData() + this.history.push(simpleDeepClone(data)) + this.activeHistoryIndex = this.history.length - 1 + this.mindMap.emit('data_change', data) + this.mindMap.emit( + 'back_forward', + this.activeHistoryIndex, + this.history.length + ) + } - /** - * @Author: 王林 - * @Date: 2021-07-11 22:34:53 - * @Desc: 回退 - */ - back(step = 1) { - if (this.activeHistoryIndex - step >= 0) { - this.activeHistoryIndex -= step - this.mindMap.emit('back_forward', this.activeHistoryIndex, this.history.length) - return simpleDeepClone(this.history[this.activeHistoryIndex]); - } + /** + * @Author: 王林 + * @Date: 2021-07-11 22:34:53 + * @Desc: 回退 + */ + back(step = 1) { + if (this.activeHistoryIndex - step >= 0) { + this.activeHistoryIndex -= step + this.mindMap.emit( + 'back_forward', + this.activeHistoryIndex, + this.history.length + ) + return simpleDeepClone(this.history[this.activeHistoryIndex]) } + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-07-12 10:45:31 - * @Desc: 前进 - */ - forward(step = 1) { - let len = this.history.length - if (this.activeHistoryIndex + step <= len - 1) { - this.activeHistoryIndex += step - this.mindMap.emit('back_forward', this.activeHistoryIndex,) - return simpleDeepClone(this.history[this.activeHistoryIndex]); - } + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-07-12 10:45:31 + * @Desc: 前进 + */ + forward(step = 1) { + let len = this.history.length + if (this.activeHistoryIndex + step <= len - 1) { + this.activeHistoryIndex += step + this.mindMap.emit('back_forward', this.activeHistoryIndex) + return simpleDeepClone(this.history[this.activeHistoryIndex]) } + } - /** - * @Author: 王林 - * @Date: 2021-05-04 15:02:58 - * @Desc: 获取渲染树数据副本 - */ - getCopyData() { - return copyRenderTree({}, this.mindMap.renderer.renderTree) - } + /** + * @Author: 王林 + * @Date: 2021-05-04 15:02:58 + * @Desc: 获取渲染树数据副本 + */ + getCopyData() { + return copyRenderTree({}, this.mindMap.renderer.renderTree) + } } -export default Command \ No newline at end of file +export default Command diff --git a/simple-mind-map/src/Drag.js b/simple-mind-map/src/Drag.js index 5cf3a3f5..f186bb05 100644 --- a/simple-mind-map/src/Drag.js +++ b/simple-mind-map/src/Drag.js @@ -1,317 +1,296 @@ -import { - bfsWalk, - throttle -} from './utils' +import { bfsWalk, throttle } from './utils' import Base from './layouts/Base' -/** - * javascript comment - * @Author: 王林25 - * @Date: 2021-11-23 17:38:55 - * @Desc: 节点拖动类 +/** + * javascript comment + * @Author: 王林25 + * @Date: 2021-11-23 17:38:55 + * @Desc: 节点拖动类 */ class Drag extends Base { - /** - * @Author: 王林 - * @Date: 2021-07-10 22:35:16 - * @Desc: 构造函数 - */ - constructor({ - mindMap - }) { - super(mindMap.renderer) - this.mindMap = mindMap - this.reset() - this.bindEvent() - } + /** + * @Author: 王林 + * @Date: 2021-07-10 22:35:16 + * @Desc: 构造函数 + */ + constructor({ mindMap }) { + super(mindMap.renderer) + this.mindMap = mindMap + this.reset() + this.bindEvent() + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-11-23 19:33:56 - * @Desc: 复位 - */ - reset() { - // 当前拖拽节点 - this.node = null - // 当前重叠节点 - this.overlapNode = null - // 当前上一个同级节点 - this.prevNode = null - // 当前下一个同级节点 - this.nextNode = null - // 画布的变换数据 - this.drawTransform = null - // 克隆节点 - this.clone = null - // 连接线 - this.line = null - // 同级位置占位符 - this.placeholder = null - // 鼠标按下位置和节点左上角的偏移量 - this.offsetX = 0 - this.offsetY = 0 - // 克隆节点左上角的坐标 - this.cloneNodeLeft = 0 - this.cloneNodeTop = 0 - // 当前鼠标是否按下 - this.isMousedown = false - // 拖拽的鼠标位置变量 - this.mouseDownX = 0 - this.mouseDownY = 0 - this.mouseMoveX = 0 - this.mouseMoveY = 0 - } + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-11-23 19:33:56 + * @Desc: 复位 + */ + reset() { + // 当前拖拽节点 + this.node = null + // 当前重叠节点 + this.overlapNode = null + // 当前上一个同级节点 + this.prevNode = null + // 当前下一个同级节点 + this.nextNode = null + // 画布的变换数据 + this.drawTransform = null + // 克隆节点 + this.clone = null + // 连接线 + this.line = null + // 同级位置占位符 + this.placeholder = null + // 鼠标按下位置和节点左上角的偏移量 + this.offsetX = 0 + this.offsetY = 0 + // 克隆节点左上角的坐标 + this.cloneNodeLeft = 0 + this.cloneNodeTop = 0 + // 当前鼠标是否按下 + this.isMousedown = false + // 拖拽的鼠标位置变量 + this.mouseDownX = 0 + this.mouseDownY = 0 + this.mouseMoveX = 0 + this.mouseMoveY = 0 + } - /** - * @Author: 王林 - * @Date: 2021-07-10 22:36:36 - * @Desc: 绑定事件 - */ - bindEvent() { - this.checkOverlapNode = throttle(this.checkOverlapNode, 300, this) - this.mindMap.on('node_mousedown', (node, e) => { - if (this.mindMap.opt.readonly || node.isGeneralization) { - return - } - if (e.which !== 1 || node.isRoot) { - return - } - e.preventDefault() - // 计算鼠标按下的位置距离节点左上角的距离 - this.drawTransform = this.mindMap.draw.transform() - let { - scaleX, - scaleY, - translateX, - translateY - } = this.drawTransform - this.offsetX = e.clientX - (node.left * scaleX + translateX) - this.offsetY = e.clientY - (node.top * scaleY + translateY) - // - this.node = node - this.isMousedown = true - let { - x, - y - } = this.mindMap.toPos(e.clientX, e.clientY) - this.mouseDownX = x - this.mouseDownY = y - }) - this.mindMap.on('mousemove', (e) => { - if (this.mindMap.opt.readonly) { - return - } - if (!this.isMousedown) { - return - } - e.preventDefault() - let { - x, - y - } = this.mindMap.toPos(e.clientX, e.clientY) - this.mouseMoveX = x - this.mouseMoveY = y - if ((Math.abs(x - this.mouseDownX) <= 10 && Math.abs(y - this.mouseDownY) <= 10) && !this.node.isDrag) { - return - } - this.mindMap.renderer.clearAllActive() - this.onMove(x, y) - }) - this.onMouseup = this.onMouseup.bind(this) - this.mindMap.on('node_mouseup', this.onMouseup) - this.mindMap.on('mouseup', this.onMouseup) - } + /** + * @Author: 王林 + * @Date: 2021-07-10 22:36:36 + * @Desc: 绑定事件 + */ + bindEvent() { + this.checkOverlapNode = throttle(this.checkOverlapNode, 300, this) + this.mindMap.on('node_mousedown', (node, e) => { + if (this.mindMap.opt.readonly || node.isGeneralization) { + return + } + if (e.which !== 1 || node.isRoot) { + return + } + e.preventDefault() + // 计算鼠标按下的位置距离节点左上角的距离 + this.drawTransform = this.mindMap.draw.transform() + let { scaleX, scaleY, translateX, translateY } = this.drawTransform + this.offsetX = e.clientX - (node.left * scaleX + translateX) + this.offsetY = e.clientY - (node.top * scaleY + translateY) + // + this.node = node + this.isMousedown = true + let { x, y } = this.mindMap.toPos(e.clientX, e.clientY) + this.mouseDownX = x + this.mouseDownY = y + }) + this.mindMap.on('mousemove', e => { + if (this.mindMap.opt.readonly) { + return + } + if (!this.isMousedown) { + return + } + e.preventDefault() + let { x, y } = this.mindMap.toPos(e.clientX, e.clientY) + this.mouseMoveX = x + this.mouseMoveY = y + if ( + Math.abs(x - this.mouseDownX) <= 10 && + Math.abs(y - this.mouseDownY) <= 10 && + !this.node.isDrag + ) { + return + } + this.mindMap.renderer.clearAllActive() + this.onMove(x, y) + }) + this.onMouseup = this.onMouseup.bind(this) + this.mindMap.on('node_mouseup', this.onMouseup) + this.mindMap.on('mouseup', this.onMouseup) + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-11-23 19:38:02 - * @Desc: 鼠标松开事件 - */ - onMouseup(e) { - if (!this.isMousedown) { - return; - } - this.isMousedown = false - let _nodeIsDrag = this.node.isDrag - this.node.isDrag = false - this.node.show() - this.removeCloneNode() - // 存在重叠子节点,则移动作为其子节点 - if (this.overlapNode) { - this.mindMap.renderer.setNodeActive(this.overlapNode, false) - this.mindMap.execCommand('MOVE_NODE_TO', this.node, this.overlapNode) - } else if (this.prevNode) { // 存在前一个相邻节点,作为其下一个兄弟节点 - this.mindMap.renderer.setNodeActive(this.prevNode, false) - this.mindMap.execCommand('INSERT_AFTER', this.node, this.prevNode) - } else if (this.nextNode) { // 存在下一个相邻节点,作为其前一个兄弟节点 - this.mindMap.renderer.setNodeActive(this.nextNode, false) - this.mindMap.execCommand('INSERT_BEFORE', this.node, this.nextNode) - } else if (_nodeIsDrag) { - // 自定义位置 - let { - x, - y - } = this.mindMap.toPos(e.clientX - this.offsetX, e.clientY - this.offsetY) - let { - scaleX, - scaleY, - translateX, - translateY - } = this.drawTransform - x = (x - translateX) / scaleX - y = (y - translateY) / scaleY - this.node.left = x - this.node.top = y - this.node.customLeft = x - this.node.customTop = y - this.mindMap.execCommand('SET_NODE_CUSTOM_POSITION', this.node, x, y) - this.mindMap.render() - } - this.reset() + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-11-23 19:38:02 + * @Desc: 鼠标松开事件 + */ + onMouseup(e) { + if (!this.isMousedown) { + return } + this.isMousedown = false + let _nodeIsDrag = this.node.isDrag + this.node.isDrag = false + this.node.show() + this.removeCloneNode() + // 存在重叠子节点,则移动作为其子节点 + if (this.overlapNode) { + this.mindMap.renderer.setNodeActive(this.overlapNode, false) + this.mindMap.execCommand('MOVE_NODE_TO', this.node, this.overlapNode) + } else if (this.prevNode) { + // 存在前一个相邻节点,作为其下一个兄弟节点 + this.mindMap.renderer.setNodeActive(this.prevNode, false) + this.mindMap.execCommand('INSERT_AFTER', this.node, this.prevNode) + } else if (this.nextNode) { + // 存在下一个相邻节点,作为其前一个兄弟节点 + this.mindMap.renderer.setNodeActive(this.nextNode, false) + this.mindMap.execCommand('INSERT_BEFORE', this.node, this.nextNode) + } else if (_nodeIsDrag) { + // 自定义位置 + let { x, y } = this.mindMap.toPos( + e.clientX - this.offsetX, + e.clientY - this.offsetY + ) + let { scaleX, scaleY, translateX, translateY } = this.drawTransform + x = (x - translateX) / scaleX + y = (y - translateY) / scaleY + this.node.left = x + this.node.top = y + this.node.customLeft = x + this.node.customTop = y + this.mindMap.execCommand('SET_NODE_CUSTOM_POSITION', this.node, x, y) + this.mindMap.render() + } + this.reset() + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-11-23 19:34:53 - * @Desc: 创建克隆节点 - */ - createCloneNode() { - if (!this.clone) { - // 节点 - this.clone = this.node.group.clone() - this.clone.opacity(0.5) - this.clone.css('z-index', 99999) - this.node.isDrag = true - this.node.hide() - // 连接线 - this.line = this.draw.path() - this.line.opacity(0.5) - this.node.styleLine(this.line, this.node) - // 同级位置占位符 - this.placeholder = this.draw.rect().fill({ - color: this.node.style.merge('lineColor', true) - }) - this.mindMap.draw.add(this.clone) - } + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-11-23 19:34:53 + * @Desc: 创建克隆节点 + */ + createCloneNode() { + if (!this.clone) { + // 节点 + this.clone = this.node.group.clone() + this.clone.opacity(0.5) + this.clone.css('z-index', 99999) + this.node.isDrag = true + this.node.hide() + // 连接线 + this.line = this.draw.path() + this.line.opacity(0.5) + this.node.styleLine(this.line, this.node) + // 同级位置占位符 + this.placeholder = this.draw.rect().fill({ + color: this.node.style.merge('lineColor', true) + }) + this.mindMap.draw.add(this.clone) } + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-11-23 19:35:16 - * @Desc: 移除克隆节点 - */ - removeCloneNode() { - if (!this.clone) { - return - } - this.clone.remove() - this.line.remove() - this.placeholder.remove() + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-11-23 19:35:16 + * @Desc: 移除克隆节点 + */ + removeCloneNode() { + if (!this.clone) { + return } + this.clone.remove() + this.line.remove() + this.placeholder.remove() + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-11-23 18:53:47 - * @Desc: 拖动中 - */ - onMove(x, y) { - if (!this.isMousedown) { - return; - } - this.createCloneNode() - let { - scaleX, - scaleY, - translateX, - translateY - } = this.drawTransform - this.cloneNodeLeft = x - this.offsetX - this.cloneNodeTop = y - this.offsetY - x = (this.cloneNodeLeft - translateX) / scaleX - y = (this.cloneNodeTop - translateY) / scaleY - let t = this.clone.transform() - this.clone.translate(x - t.translateX, y - t.translateY) - // 连接线 - let parent = this.node.parent - this.line.plot(this.quadraticCurvePath(parent.left + parent.width / 2, parent.top + parent.height / 2, x + this.node.width / 2, y + this.node.height / 2)) - this.checkOverlapNode() + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-11-23 18:53:47 + * @Desc: 拖动中 + */ + onMove(x, y) { + if (!this.isMousedown) { + return } + this.createCloneNode() + let { scaleX, scaleY, translateX, translateY } = this.drawTransform + this.cloneNodeLeft = x - this.offsetX + this.cloneNodeTop = y - this.offsetY + x = (this.cloneNodeLeft - translateX) / scaleX + y = (this.cloneNodeTop - translateY) / scaleY + let t = this.clone.transform() + this.clone.translate(x - t.translateX, y - t.translateY) + // 连接线 + let parent = this.node.parent + this.line.plot( + this.quadraticCurvePath( + parent.left + parent.width / 2, + parent.top + parent.height / 2, + x + this.node.width / 2, + y + this.node.height / 2 + ) + ) + this.checkOverlapNode() + } - /** - * @Author: 王林 - * @Date: 2021-07-11 10:20:43 - * @Desc: 检测重叠节点 - */ - checkOverlapNode() { - if (!this.drawTransform) { - return - } - let { - scaleX, - scaleY, - translateX, - translateY - } = this.drawTransform - let checkRight = this.cloneNodeLeft + this.node.width * scaleX - let checkBottom = this.cloneNodeTop + this.node.height * scaleX - this.overlapNode = null - this.prevNode = null - this.nextNode = null - this.placeholder.size(0, 0) - bfsWalk(this.mindMap.renderer.root, (node) => { - if (node.nodeData.data.isActive) { - this.mindMap.renderer.setNodeActive(node, false) - } - if (node === this.node || this.node.isParent(node)) { - return - } - if (this.overlapNode || this.prevNode && this.nextNode) { - return - } - let { - left, - top, - width, - height - } = node - let _left = left - let _top = top - let _bottom = top + height - let right = (left + width) * scaleX + translateX - let bottom = (top + height) * scaleY + translateY - left = left * scaleX + translateX - top = top * scaleY + translateY - // 检测是否重叠 - if (!this.overlapNode) { - if ( - left <= checkRight && right >= this.cloneNodeLeft && - top <= checkBottom && bottom >= this.cloneNodeTop - ) { - this.overlapNode = node - } - } - // 检测兄弟节点位置 - if (!this.prevNode && !this.nextNode && this.node.isBrother(node)) { - if (left <= checkRight && right >= this.cloneNodeLeft) { - if (this.cloneNodeTop > bottom && this.cloneNodeTop <= bottom + 10) { - this.prevNode = node - this.placeholder.size(node.width, 10).move(_left, _bottom) - } else if (checkBottom < top && checkBottom >= top - 10) { - this.nextNode = node - this.placeholder.size(node.width, 10).move(_left, _top - 10) - } - } - } - }) - if (this.overlapNode) { - this.mindMap.renderer.setNodeActive(this.overlapNode, true) - } + /** + * @Author: 王林 + * @Date: 2021-07-11 10:20:43 + * @Desc: 检测重叠节点 + */ + checkOverlapNode() { + if (!this.drawTransform) { + return } + let { scaleX, scaleY, translateX, translateY } = this.drawTransform + let checkRight = this.cloneNodeLeft + this.node.width * scaleX + let checkBottom = this.cloneNodeTop + this.node.height * scaleX + this.overlapNode = null + this.prevNode = null + this.nextNode = null + this.placeholder.size(0, 0) + bfsWalk(this.mindMap.renderer.root, node => { + if (node.nodeData.data.isActive) { + this.mindMap.renderer.setNodeActive(node, false) + } + if (node === this.node || this.node.isParent(node)) { + return + } + if (this.overlapNode || (this.prevNode && this.nextNode)) { + return + } + let { left, top, width, height } = node + let _left = left + let _top = top + let _bottom = top + height + let right = (left + width) * scaleX + translateX + let bottom = (top + height) * scaleY + translateY + left = left * scaleX + translateX + top = top * scaleY + translateY + // 检测是否重叠 + if (!this.overlapNode) { + if ( + left <= checkRight && + right >= this.cloneNodeLeft && + top <= checkBottom && + bottom >= this.cloneNodeTop + ) { + this.overlapNode = node + } + } + // 检测兄弟节点位置 + if (!this.prevNode && !this.nextNode && this.node.isBrother(node)) { + if (left <= checkRight && right >= this.cloneNodeLeft) { + if (this.cloneNodeTop > bottom && this.cloneNodeTop <= bottom + 10) { + this.prevNode = node + this.placeholder.size(node.width, 10).move(_left, _bottom) + } else if (checkBottom < top && checkBottom >= top - 10) { + this.nextNode = node + this.placeholder.size(node.width, 10).move(_left, _top - 10) + } + } + } + }) + if (this.overlapNode) { + this.mindMap.renderer.setNodeActive(this.overlapNode, true) + } + } } -export default Drag \ No newline at end of file +export default Drag diff --git a/simple-mind-map/src/Event.js b/simple-mind-map/src/Event.js index f11b391b..d2dc97ea 100644 --- a/simple-mind-map/src/Event.js +++ b/simple-mind-map/src/Event.js @@ -1,182 +1,182 @@ import EventEmitter from 'eventemitter3' -/** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-07 14:53:09 - * @Desc: 事件类 +/** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-07 14:53:09 + * @Desc: 事件类 */ class Event extends EventEmitter { - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-07 14:53:25 - * @Desc: 构造函数 - */ - constructor(opt = {}) { - super() - this.opt = opt - this.mindMap = opt.mindMap - this.isLeftMousedown = false - this.mousedownPos = { - x: 0, - y: 0 - } - this.mousemovePos = { - x: 0, - y: 0 - } - this.mousemoveOffset = { - x: 0, - y: 0 - } - this.bindFn() - this.bind() + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-07 14:53:25 + * @Desc: 构造函数 + */ + constructor(opt = {}) { + super() + this.opt = opt + this.mindMap = opt.mindMap + this.isLeftMousedown = false + this.mousedownPos = { + x: 0, + y: 0 } + this.mousemovePos = { + x: 0, + y: 0 + } + this.mousemoveOffset = { + x: 0, + y: 0 + } + this.bindFn() + this.bind() + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-07 15:52:24 - * @Desc: 绑定函数上下文 - */ - bindFn() { - this.onDrawClick = this.onDrawClick.bind(this) - this.onMousedown = this.onMousedown.bind(this) - this.onMousemove = this.onMousemove.bind(this) - this.onMouseup = this.onMouseup.bind(this) - this.onMousewheel = this.onMousewheel.bind(this) - this.onContextmenu = this.onContextmenu.bind(this) - this.onSvgMousedown = this.onSvgMousedown.bind(this) - } + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-07 15:52:24 + * @Desc: 绑定函数上下文 + */ + bindFn() { + this.onDrawClick = this.onDrawClick.bind(this) + this.onMousedown = this.onMousedown.bind(this) + this.onMousemove = this.onMousemove.bind(this) + this.onMouseup = this.onMouseup.bind(this) + this.onMousewheel = this.onMousewheel.bind(this) + this.onContextmenu = this.onContextmenu.bind(this) + this.onSvgMousedown = this.onSvgMousedown.bind(this) + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-07 14:53:43 - * @Desc: 绑定事件 - */ - bind() { - this.mindMap.svg.on('click', this.onDrawClick) - this.mindMap.el.addEventListener('mousedown', this.onMousedown) - this.mindMap.svg.on('mousedown', this.onSvgMousedown) - window.addEventListener('mousemove', this.onMousemove) - window.addEventListener('mouseup', this.onMouseup) - // 兼容火狐浏览器 - if(window.navigator.userAgent.toLowerCase().indexOf("firefox") != -1){ - this.mindMap.el.addEventListener('DOMMouseScroll', this.onMousewheel) - } else { - this.mindMap.el.addEventListener('mousewheel', this.onMousewheel) - } - this.mindMap.svg.on('contextmenu', this.onContextmenu) + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-07 14:53:43 + * @Desc: 绑定事件 + */ + bind() { + this.mindMap.svg.on('click', this.onDrawClick) + this.mindMap.el.addEventListener('mousedown', this.onMousedown) + this.mindMap.svg.on('mousedown', this.onSvgMousedown) + window.addEventListener('mousemove', this.onMousemove) + window.addEventListener('mouseup', this.onMouseup) + // 兼容火狐浏览器 + if (window.navigator.userAgent.toLowerCase().indexOf('firefox') != -1) { + this.mindMap.el.addEventListener('DOMMouseScroll', this.onMousewheel) + } else { + this.mindMap.el.addEventListener('mousewheel', this.onMousewheel) } + this.mindMap.svg.on('contextmenu', this.onContextmenu) + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-07 15:40:51 - * @Desc: 解绑事件 - */ - unbind() { - this.mindMap.svg.off('click', this.onDrawClick) - this.mindMap.el.removeEventListener('mousedown', this.onMousedown) - window.removeEventListener('mousemove', this.onMousemove) - window.removeEventListener('mouseup', this.onMouseup) - this.mindMap.el.removeEventListener('mousewheel', this.onMousewheel) - this.mindMap.svg.off('contextmenu', this.onContextmenu) - } + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-07 15:40:51 + * @Desc: 解绑事件 + */ + unbind() { + this.mindMap.svg.off('click', this.onDrawClick) + this.mindMap.el.removeEventListener('mousedown', this.onMousedown) + window.removeEventListener('mousemove', this.onMousemove) + window.removeEventListener('mouseup', this.onMouseup) + this.mindMap.el.removeEventListener('mousewheel', this.onMousewheel) + this.mindMap.svg.off('contextmenu', this.onContextmenu) + } - /** - * @Author: 王林 - * @Date: 2021-04-24 13:19:39 - * @Desc: 画布的单击事件 - */ - onDrawClick(e) { - this.emit('draw_click', e) - } + /** + * @Author: 王林 + * @Date: 2021-04-24 13:19:39 + * @Desc: 画布的单击事件 + */ + onDrawClick(e) { + this.emit('draw_click', e) + } - /** - * @Author: 王林 - * @Date: 2021-07-16 13:37:30 - * @Desc: svg画布的鼠标按下事件 - */ - onSvgMousedown(e) { - this.emit('svg_mousedown', e) - } + /** + * @Author: 王林 + * @Date: 2021-07-16 13:37:30 + * @Desc: svg画布的鼠标按下事件 + */ + onSvgMousedown(e) { + this.emit('svg_mousedown', e) + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-07 15:17:35 - * @Desc: 鼠标按下事件 - */ - onMousedown(e) { - // e.preventDefault() - // 鼠标左键 - if (e.which === 1) { - this.isLeftMousedown = true - } - this.mousedownPos.x = e.clientX - this.mousedownPos.y = e.clientY - this.emit('mousedown', e, this) + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-07 15:17:35 + * @Desc: 鼠标按下事件 + */ + onMousedown(e) { + // e.preventDefault() + // 鼠标左键 + if (e.which === 1) { + this.isLeftMousedown = true } + this.mousedownPos.x = e.clientX + this.mousedownPos.y = e.clientY + this.emit('mousedown', e, this) + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-07 15:18:32 - * @Desc: 鼠标移动事件 - */ - onMousemove(e) { - // e.preventDefault() - this.mousemovePos.x = e.clientX - this.mousemovePos.y = e.clientY - this.mousemoveOffset.x = e.clientX - this.mousedownPos.x - this.mousemoveOffset.y = e.clientY - this.mousedownPos.y - this.emit('mousemove', e, this) - if (this.isLeftMousedown) { - this.emit('drag', e, this) - } + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-07 15:18:32 + * @Desc: 鼠标移动事件 + */ + onMousemove(e) { + // e.preventDefault() + this.mousemovePos.x = e.clientX + this.mousemovePos.y = e.clientY + this.mousemoveOffset.x = e.clientX - this.mousedownPos.x + this.mousemoveOffset.y = e.clientY - this.mousedownPos.y + this.emit('mousemove', e, this) + if (this.isLeftMousedown) { + this.emit('drag', e, this) } + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-07 15:18:57 - * @Desc: 鼠标松开事件 - */ - onMouseup(e) { - this.isLeftMousedown = false - this.emit('mouseup', e, this) - } + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-07 15:18:57 + * @Desc: 鼠标松开事件 + */ + onMouseup(e) { + this.isLeftMousedown = false + this.emit('mouseup', e, this) + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-07 15:46:27 - * @Desc: 鼠标滚动 - */ - onMousewheel(e) { - e.stopPropagation() - e.preventDefault() - let dir - if ((e.wheelDeltaY || e.detail) > 0) { - dir = 'up' - } else { - dir = 'down' - } - this.emit('mousewheel', e, dir, this) + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-07 15:46:27 + * @Desc: 鼠标滚动 + */ + onMousewheel(e) { + e.stopPropagation() + e.preventDefault() + let dir + if ((e.wheelDeltaY || e.detail) > 0) { + dir = 'up' + } else { + dir = 'down' } + this.emit('mousewheel', e, dir, this) + } - /** - * @Author: 王林 - * @Date: 2021-07-10 22:34:13 - * @Desc: 鼠标右键菜单事件 - */ - onContextmenu(e) { - e.preventDefault() - this.emit('contextmenu', e) - } + /** + * @Author: 王林 + * @Date: 2021-07-10 22:34:13 + * @Desc: 鼠标右键菜单事件 + */ + onContextmenu(e) { + e.preventDefault() + this.emit('contextmenu', e) + } } -export default Event \ No newline at end of file +export default Event diff --git a/simple-mind-map/src/Export.js b/simple-mind-map/src/Export.js index f9b2f405..2dcd3a9b 100644 --- a/simple-mind-map/src/Export.js +++ b/simple-mind-map/src/Export.js @@ -1,249 +1,265 @@ import { imgToDataUrl, downloadFile } from './utils' import JsPDF from 'jspdf' -import { - SVG, -} from '@svgdotjs/svg.js' +import { SVG } from '@svgdotjs/svg.js' const URL = window.URL || window.webkitURL || window -/** - * @Author: 王林 - * @Date: 2021-07-01 22:05:16 - * @Desc: 导出类 +/** + * @Author: 王林 + * @Date: 2021-07-01 22:05:16 + * @Desc: 导出类 */ class Export { - /** - * @Author: 王林 - * @Date: 2021-07-01 22:05:42 - * @Desc: 构造函数 - */ - constructor(opt) { - this.mindMap = opt.mindMap - this.exportPadding = this.mindMap.opt.exportPadding - } + /** + * @Author: 王林 + * @Date: 2021-07-01 22:05:42 + * @Desc: 构造函数 + */ + constructor(opt) { + this.mindMap = opt.mindMap + this.exportPadding = this.mindMap.opt.exportPadding + } - /** - * @Author: 王林 - * @Date: 2021-07-02 07:44:06 - * @Desc: 导出 - */ - async export(type, isDownload = true, name = '思维导图', ...args) { - if (this[type]) { - let result = await this[type](name, ...args) - if (isDownload && type !== 'pdf') { - downloadFile(result, name + '.' + type) - } - return result - } else { - return null + /** + * @Author: 王林 + * @Date: 2021-07-02 07:44:06 + * @Desc: 导出 + */ + async export(type, isDownload = true, name = '思维导图', ...args) { + if (this[type]) { + let result = await this[type](name, ...args) + if (isDownload && type !== 'pdf') { + downloadFile(result, name + '.' + type) + } + return result + } else { + return null + } + } + + /** + * @Author: 王林 + * @Date: 2021-07-04 14:57:40 + * @Desc: 获取svg数据 + */ + async getSvgData() { + let { svg, svgHTML } = this.mindMap.miniMap.getMiniMap() + // 把图片的url转换成data:url类型,否则导出会丢失图片 + let imageList = svg.find('image') + let task = imageList.map(async item => { + let imgUlr = item.attr('href') || item.attr('xlink:href') + let imgData = await imgToDataUrl(imgUlr) + item.attr('href', imgData) + }) + await Promise.all(task) + return { + node: svg, + str: svgHTML + } + } + + /** + * @Author: 王林 + * @Date: 2021-07-04 15:25:19 + * @Desc: svg转png + */ + svgToPng(svgSrc) { + return new Promise((resolve, reject) => { + const img = new Image() + // 跨域图片需要添加这个属性,否则画布被污染了无法导出图片 + img.setAttribute('crossOrigin', 'anonymous') + img.onload = async () => { + try { + let canvas = document.createElement('canvas') + canvas.width = img.width + this.exportPadding * 2 + canvas.height = img.height + this.exportPadding * 2 + let ctx = canvas.getContext('2d') + // 绘制背景 + await this.drawBackgroundToCanvas(ctx, canvas.width, canvas.height) + // 图片绘制到canvas里 + ctx.drawImage( + img, + 0, + 0, + img.width, + img.height, + this.exportPadding, + this.exportPadding, + img.width, + img.height + ) + resolve(canvas.toDataURL()) + } catch (error) { + reject(error) } - } + } + img.onerror = e => { + reject(e) + } + img.src = svgSrc + }) + } - /** - * @Author: 王林 - * @Date: 2021-07-04 14:57:40 - * @Desc: 获取svg数据 - */ - async getSvgData() { - let { svg, svgHTML } = this.mindMap.miniMap.getMiniMap() - // 把图片的url转换成data:url类型,否则导出会丢失图片 - let imageList = svg.find('image') - let task = imageList.map(async (item) => { - let imgUlr = item.attr('href') || item.attr('xlink:href') - let imgData = await imgToDataUrl(imgUlr) - item.attr('href', imgData) - }) - await Promise.all(task) - return { - node: svg, - str: svgHTML + /** + * @Author: 王林 + * @Date: 2021-07-04 15:32:07 + * @Desc: 在canvas上绘制思维导图背景 + */ + drawBackgroundToCanvas(ctx, width, height) { + return new Promise((resolve, reject) => { + let { + backgroundColor = '#fff', + backgroundImage, + backgroundRepeat = 'repeat' + } = this.mindMap.themeConfig + // 背景颜色 + ctx.save() + ctx.rect(0, 0, width, height) + ctx.fillStyle = backgroundColor + ctx.fill() + ctx.restore() + // 背景图片 + if (backgroundImage && backgroundImage !== 'none') { + ctx.save() + let img = new Image() + img.src = backgroundImage + img.onload = () => { + let pat = ctx.createPattern(img, backgroundRepeat) + ctx.rect(0, 0, width, height) + ctx.fillStyle = pat + ctx.fill() + ctx.restore() + resolve() } - } - - /** - * @Author: 王林 - * @Date: 2021-07-04 15:25:19 - * @Desc: svg转png - */ - svgToPng(svgSrc) { - return new Promise((resolve, reject) => { - const img = new Image() - // 跨域图片需要添加这个属性,否则画布被污染了无法导出图片 - img.setAttribute('crossOrigin', 'anonymous') - img.onload = async () => { - try { - let canvas = document.createElement('canvas') - canvas.width = img.width + this.exportPadding * 2 - canvas.height = img.height + this.exportPadding * 2 - let ctx = canvas.getContext('2d') - // 绘制背景 - await this.drawBackgroundToCanvas(ctx, canvas.width, canvas.height) - // 图片绘制到canvas里 - ctx.drawImage(img, 0, 0, img.width, img.height, this.exportPadding, this.exportPadding, img.width, img.height) - resolve(canvas.toDataURL()) - } catch (error) { - reject(error) - } - } - img.onerror = (e) => { - reject(e) - } - img.src = svgSrc - }) - } - - /** - * @Author: 王林 - * @Date: 2021-07-04 15:32:07 - * @Desc: 在canvas上绘制思维导图背景 - */ - drawBackgroundToCanvas(ctx, width, height) { - return new Promise((resolve, rejct) => { - let { backgroundColor = '#fff', backgroundImage, backgroundRepeat = "repeat" } = this.mindMap.themeConfig - // 背景颜色 - ctx.save() - ctx.rect(0, 0, width, height) - ctx.fillStyle = backgroundColor - ctx.fill() - ctx.restore() - // 背景图片 - if (backgroundImage && backgroundImage !== 'none') { - ctx.save() - let img = new Image() - img.src = backgroundImage - img.onload = () => { - let pat = ctx.createPattern(img, backgroundRepeat) - ctx.rect(0, 0, width, height) - ctx.fillStyle = pat - ctx.fill() - ctx.restore() - resolve() - } - img.onerror = (e) => { - rejct(e) - } - } else { - resolve() - } - }) - } - - /** - * @Author: 王林 - * @Date: 2021-07-01 22:09:51 - * @Desc: 导出为png - * 方法1.把svg的图片都转化成data:url格式,再转换 - * 方法2.把svg的图片提取出来再挨个绘制到canvas里,最后一起转换 - */ - async png() { - let { str } = await this.getSvgData() - // 转换成blob数据 - let blob = new Blob([str], { - type: 'image/svg+xml' - }) - // 转换成data:url数据 - let svgUrl = URL.createObjectURL(blob) - // 绘制到canvas上 - let imgDataUrl = await this.svgToPng(svgUrl) - URL.revokeObjectURL(svgUrl) - return imgDataUrl - } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2022-08-08 19:23:08 - * @Desc: 导出为pdf - */ - async pdf(name) { - let img = await this.png() - let pdf = new JsPDF('', 'pt', 'a4') - let a4Width = 595 - let a4Height = 841 - let a4Ratio = a4Width / a4Height - let image = new Image() - image.onload = () => { - let imageWidth = image.width - let imageHeight = image.height - let imageRatio = imageWidth / imageHeight - let w, h - if (imageWidth <= a4Width && imageHeight <= a4Height) { - // 使用图片原始宽高 - w = imageWidth - h = imageHeight - } else if (a4Ratio > imageRatio) { - // 以a4Height为高度,缩放图片宽度 - w = imageRatio * a4Height - h = a4Height - } else { - // 以a4Width为宽度,缩放图片高度 - w = a4Width - h = a4Width / imageRatio - } - pdf.addImage(img, 'PNG', (a4Width - w) / 2, (a4Height - h) / 2, w, h) - pdf.save(name) + img.onerror = e => { + reject(e) } - image.src = img - } + } else { + resolve() + } + }) + } - /** - * @Author: 王林 - * @Date: 2021-07-04 15:32:07 - * @Desc: 在svg上绘制思维导图背景 - */ - drawBackgroundToSvg(svg) { - return new Promise(async (resolve, rejct) => { - let { backgroundColor = '#fff', backgroundImage, backgroundRepeat = "repeat" } = this.mindMap.themeConfig - // 背景颜色 - svg.css('background-color', backgroundColor) - // 背景图片 - if (backgroundImage && backgroundImage !== 'none') { - let imgDataUrl = await imgToDataUrl(backgroundImage) - svg.css('background-image', `url(${imgDataUrl})`) - svg.css('background-repeat', backgroundRepeat) - resolve() - } else { - resolve() - } - }) - } + /** + * @Author: 王林 + * @Date: 2021-07-01 22:09:51 + * @Desc: 导出为png + * 方法1.把svg的图片都转化成data:url格式,再转换 + * 方法2.把svg的图片提取出来再挨个绘制到canvas里,最后一起转换 + */ + async png() { + let { str } = await this.getSvgData() + // 转换成blob数据 + let blob = new Blob([str], { + type: 'image/svg+xml' + }) + // 转换成data:url数据 + let svgUrl = URL.createObjectURL(blob) + // 绘制到canvas上 + let imgDataUrl = await this.svgToPng(svgUrl) + URL.revokeObjectURL(svgUrl) + return imgDataUrl + } - /** - * @Author: 王林 - * @Date: 2021-07-04 14:54:07 - * @Desc: 导出为svg - */ - async svg(name) { - let { node } = await this.getSvgData() - node.first().before(SVG(`${name}`)) - await this.drawBackgroundToSvg(node) - let str = node.svg() - // 转换成blob数据 - let blob = new Blob([str], { - type: 'image/svg+xml' - }) - return URL.createObjectURL(blob) + /** + * javascript comment + * @Author: 王林25 + * @Date: 2022-08-08 19:23:08 + * @Desc: 导出为pdf + */ + async pdf(name) { + let img = await this.png() + let pdf = new JsPDF('', 'pt', 'a4') + let a4Width = 595 + let a4Height = 841 + let a4Ratio = a4Width / a4Height + let image = new Image() + image.onload = () => { + let imageWidth = image.width + let imageHeight = image.height + let imageRatio = imageWidth / imageHeight + let w, h + if (imageWidth <= a4Width && imageHeight <= a4Height) { + // 使用图片原始宽高 + w = imageWidth + h = imageHeight + } else if (a4Ratio > imageRatio) { + // 以a4Height为高度,缩放图片宽度 + w = imageRatio * a4Height + h = a4Height + } else { + // 以a4Width为宽度,缩放图片高度 + w = a4Width + h = a4Width / imageRatio + } + pdf.addImage(img, 'PNG', (a4Width - w) / 2, (a4Height - h) / 2, w, h) + pdf.save(name) } + image.src = img + } - /** - * @Author: 王林 - * @Date: 2021-08-03 22:19:17 - * @Desc: 导出为json - */ - json (name, withConfig = true) { - let data = this.mindMap.getData(withConfig) - let str = JSON.stringify(data) - let blob = new Blob([str]) - return URL.createObjectURL(blob) - } + /** + * @Author: 王林 + * @Date: 2021-07-04 15:32:07 + * @Desc: 在svg上绘制思维导图背景 + */ + drawBackgroundToSvg(svg) { + return new Promise(async resolve => { + let { + backgroundColor = '#fff', + backgroundImage, + backgroundRepeat = 'repeat' + } = this.mindMap.themeConfig + // 背景颜色 + svg.css('background-color', backgroundColor) + // 背景图片 + if (backgroundImage && backgroundImage !== 'none') { + let imgDataUrl = await imgToDataUrl(backgroundImage) + svg.css('background-image', `url(${imgDataUrl})`) + svg.css('background-repeat', backgroundRepeat) + resolve() + } else { + resolve() + } + }) + } - /** - * @Author: 王林 - * @Date: 2021-08-03 22:24:24 - * @Desc: 专有文件,其实就是json文件 - */ - smm (name, withConfig) { - return this.json(name, withConfig); - } + /** + * @Author: 王林 + * @Date: 2021-07-04 14:54:07 + * @Desc: 导出为svg + */ + async svg(name) { + let { node } = await this.getSvgData() + node.first().before(SVG(`${name}`)) + await this.drawBackgroundToSvg(node) + let str = node.svg() + // 转换成blob数据 + let blob = new Blob([str], { + type: 'image/svg+xml' + }) + return URL.createObjectURL(blob) + } + + /** + * @Author: 王林 + * @Date: 2021-08-03 22:19:17 + * @Desc: 导出为json + */ + json(name, withConfig = true) { + let data = this.mindMap.getData(withConfig) + let str = JSON.stringify(data) + let blob = new Blob([str]) + return URL.createObjectURL(blob) + } + + /** + * @Author: 王林 + * @Date: 2021-08-03 22:24:24 + * @Desc: 专有文件,其实就是json文件 + */ + smm(name, withConfig) { + return this.json(name, withConfig) + } } export default Export diff --git a/simple-mind-map/src/KeyCommand.js b/simple-mind-map/src/KeyCommand.js index c152a487..c50048ca 100644 --- a/simple-mind-map/src/KeyCommand.js +++ b/simple-mind-map/src/KeyCommand.js @@ -1,200 +1,200 @@ -import { keyMap } from './utils/keyMap'; -/** - * @Author: 王林 - * @Date: 2021-04-24 15:20:46 - * @Desc: 快捷按键、命令处理类 +import { keyMap } from './utils/keyMap' +/** + * @Author: 王林 + * @Date: 2021-04-24 15:20:46 + * @Desc: 快捷按键、命令处理类 */ export default class KeyCommand { - /** - * @Author: 王林 - * @Date: 2021-04-24 15:21:32 - * @Desc: 构造函数 - */ - constructor(opt) { - this.opt = opt - this.mindMap = opt.mindMap - this.shortcutMap = { - //Enter: [fn] + /** + * @Author: 王林 + * @Date: 2021-04-24 15:21:32 + * @Desc: 构造函数 + */ + constructor(opt) { + this.opt = opt + this.mindMap = opt.mindMap + this.shortcutMap = { + //Enter: [fn] + } + this.shortcutMapCache = {} + this.isPause = false + this.bindEvent() + } + + /** + * @Author: 王林 + * @Date: 2022-08-14 08:57:55 + * @Desc: 暂停快捷键响应 + */ + pause() { + this.isPause = true + } + + /** + * @Author: 王林 + * @Date: 2022-08-14 08:58:43 + * @Desc: 恢复快捷键响应 + */ + recovery() { + this.isPause = false + } + + /** + * javascript comment + * @Author: 王林25 + * @Date: 2022-08-16 16:29:01 + * @Desc: 保存当前注册的快捷键数据,然后清空快捷键数据 + */ + save() { + this.shortcutMapCache = this.shortcutMap + this.shortcutMap = {} + } + + /** + * javascript comment + * @Author: 王林25 + * @Date: 2022-08-16 16:29:38 + * @Desc: 恢复保存的快捷键数据,然后清空缓存数据 + */ + restore() { + this.shortcutMap = this.shortcutMapCache + this.shortcutMapCache = {} + } + + /** + * @Author: 王林 + * @Date: 2021-04-24 15:23:22 + * @Desc: 绑定事件 + */ + bindEvent() { + window.addEventListener('keydown', e => { + if (this.isPause) { + return + } + Object.keys(this.shortcutMap).forEach(key => { + if (this.checkKey(e, key)) { + e.stopPropagation() + e.preventDefault() + this.shortcutMap[key].forEach(fn => { + fn() + }) } - this.shortcutMapCache = {} - this.isPause = false - this.bindEvent() - } + }) + }) + } - /** - * @Author: 王林 - * @Date: 2022-08-14 08:57:55 - * @Desc: 暂停快捷键响应 - */ - pause() { - this.isPause = true + /** + * @Author: 王林 + * @Date: 2021-04-24 19:24:53 + * @Desc: 检查键值是否符合 + */ + checkKey(e, key) { + let o = this.getOriginEventCodeArr(e) + let k = this.getKeyCodeArr(key) + if (o.length !== k.length) { + return false } - - /** - * @Author: 王林 - * @Date: 2022-08-14 08:58:43 - * @Desc: 恢复快捷键响应 - */ - recovery() { - this.isPause = false + for (let i = 0; i < o.length; i++) { + let index = k.findIndex(item => { + return item === o[i] + }) + if (index === -1) { + return false + } else { + k.splice(index, 1) + } } + return true + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2022-08-16 16:29:01 - * @Desc: 保存当前注册的快捷键数据,然后清空快捷键数据 - */ - save() { - this.shortcutMapCache = this.shortcutMap - this.shortcutMap = {} + /** + * @Author: 王林 + * @Date: 2021-04-24 19:15:19 + * @Desc: 获取事件对象里的键值数组 + */ + getOriginEventCodeArr(e) { + let arr = [] + if (e.ctrlKey || e.metaKey) { + arr.push(keyMap['Control']) } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2022-08-16 16:29:38 - * @Desc: 恢复保存的快捷键数据,然后清空缓存数据 - */ - restore() { - this.shortcutMap = this.shortcutMapCache - this.shortcutMapCache = {} + if (e.altKey) { + arr.push(keyMap['Alt']) } - - /** - * @Author: 王林 - * @Date: 2021-04-24 15:23:22 - * @Desc: 绑定事件 - */ - bindEvent() { - window.addEventListener('keydown', (e) => { - if (this.isPause) { - return - } - Object.keys(this.shortcutMap).forEach((key) => { - if (this.checkKey(e, key)) { - e.stopPropagation() - e.preventDefault() - this.shortcutMap[key].forEach((fn) => { - fn() - }) - } - }) - }) + if (e.shiftKey) { + arr.push(keyMap['Shift']) } + if (!arr.includes(e.keyCode)) { + arr.push(e.keyCode) + } + return arr + } - /** - * @Author: 王林 - * @Date: 2021-04-24 19:24:53 - * @Desc: 检查键值是否符合 - */ - checkKey(e, key) { - let o = this.getOriginEventCodeArr(e) - let k = this.getKeyCodeArr(key) - if (o.length !== k.length) { - return false + /** + * @Author: 王林 + * @Date: 2021-04-24 19:40:11 + * @Desc: 获取快捷键对应的键值数组 + */ + getKeyCodeArr(key) { + let keyArr = key.split(/\s*\+\s*/) + let arr = [] + keyArr.forEach(item => { + arr.push(keyMap[item]) + }) + return arr + } + + /** + * @Author: 王林 + * @Date: 2021-04-24 15:23:00 + * @Desc: 添加快捷键命令 + * Enter + * Tab | Insert + * Shift + a + */ + addShortcut(key, fn) { + key.split(/\s*\|\s*/).forEach(item => { + if (this.shortcutMap[item]) { + this.shortcutMap[item].push(fn) + } else { + this.shortcutMap[item] = [fn] + } + }) + } + + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-07-27 14:06:16 + * @Desc: 移除快捷键命令 + */ + removeShortcut(key, fn) { + key.split(/\s*\|\s*/).forEach(item => { + if (this.shortcutMap[item]) { + if (fn) { + let index = this.shortcutMap[item].findIndex(f => { + return f === fn + }) + if (index !== -1) { + this.shortcutMap[item].splice(index, 1) + } + } else { + this.shortcutMap[item] = [] + delete this.shortcutMap[item] } - for (let i = 0; i < o.length; i++) { - let index = k.findIndex((item) => { - return item === o[i]; - }) - if (index === -1) { - return false - } else { - k.splice(index, 1) - } - } - return true - } + } + }) + } - /** - * @Author: 王林 - * @Date: 2021-04-24 19:15:19 - * @Desc: 获取事件对象里的键值数组 - */ - getOriginEventCodeArr(e) { - let arr = [] - if (e.ctrlKey || e.metaKey) { - arr.push(keyMap['Control']) - } - if (e.altKey) { - arr.push(keyMap['Alt']) - } - if (e.shiftKey) { - arr.push(keyMap['Shift']) - } - if (!arr.includes(e.keyCode)) { - arr.push(e.keyCode) - } - return arr - } - - /** - * @Author: 王林 - * @Date: 2021-04-24 19:40:11 - * @Desc: 获取快捷键对应的键值数组 - */ - getKeyCodeArr(key) { - let keyArr = key.split(/\s*\+\s*/) - let arr = [] - keyArr.forEach((item) => { - arr.push(keyMap[item]) - }) - return arr - } - - /** - * @Author: 王林 - * @Date: 2021-04-24 15:23:00 - * @Desc: 添加快捷键命令 - * Enter - * Tab | Insert - * Shift + a - */ - addShortcut(key, fn) { - key.split(/\s*\|\s*/).forEach((item) => { - if (this.shortcutMap[item]) { - this.shortcutMap[item].push(fn) - } else { - this.shortcutMap[item] = [fn] - } - }) - } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-07-27 14:06:16 - * @Desc: 移除快捷键命令 - */ - removeShortcut(key, fn) { - key.split(/\s*\|\s*/).forEach((item) => { - if (this.shortcutMap[item]) { - if (fn) { - let index = this.shortcutMap[item].findIndex((f) => { - return f === fn - }) - if (index !== -1) { - this.shortcutMap[item].splice(index, 1) - } - } else { - this.shortcutMap[item] = [] - delete this.shortcutMap[item] - } - } - }) - } - - /** - * @Author: 王林 - * @Date: 2022-08-14 08:49:58 - * @Desc: 获取指定快捷键的处理函数 - */ - getShortcutFn(key) { - let res = [] - key.split(/\s*\|\s*/).forEach((item) => { - res = this.shortcutMap[item] || [] - }) - return res - } -} \ No newline at end of file + /** + * @Author: 王林 + * @Date: 2022-08-14 08:49:58 + * @Desc: 获取指定快捷键的处理函数 + */ + getShortcutFn(key) { + let res = [] + key.split(/\s*\|\s*/).forEach(item => { + res = this.shortcutMap[item] || [] + }) + return res + } +} diff --git a/simple-mind-map/src/MiniMap.js b/simple-mind-map/src/MiniMap.js index 8a68f1dd..b4924975 100644 --- a/simple-mind-map/src/MiniMap.js +++ b/simple-mind-map/src/MiniMap.js @@ -7,16 +7,16 @@ class MiniMap { * @Desc: 构造函数 */ constructor(opt) { - this.mindMap = opt.mindMap; - this.isMousedown = false; + this.mindMap = opt.mindMap + this.isMousedown = false this.mousedownPos = { x: 0, - y: 0, - }; + y: 0 + } this.startViewPos = { x: 0, - y: 0, - }; + y: 0 + } } /** @@ -26,39 +26,39 @@ class MiniMap { * @Desc: 获取小地图相关数据 */ getMiniMap() { - const svg = this.mindMap.svg; - const draw = this.mindMap.draw; + const svg = this.mindMap.svg + const draw = this.mindMap.draw // 保存原始信息 - const origWidth = svg.width(); - const origHeight = svg.height(); - const origTransform = draw.transform(); - const elRect = this.mindMap.el.getBoundingClientRect(); + const origWidth = svg.width() + const origHeight = svg.height() + const origTransform = draw.transform() + const elRect = this.mindMap.el.getBoundingClientRect() // 去除放大缩小的变换效果 - draw.scale(1 / origTransform.scaleX, 1 / origTransform.scaleY); + draw.scale(1 / origTransform.scaleX, 1 / origTransform.scaleY) // 获取变换后的位置尺寸信息,其实是getBoundingClientRect方法的包装方法 - const rect = draw.rbox(); + const rect = draw.rbox() // 将svg设置为实际内容的宽高 - svg.size(rect.width, rect.height); + svg.size(rect.width, rect.height) // 把实际内容变换 - draw.translate(-rect.x + elRect.left, -rect.y + elRect.top); + draw.translate(-rect.x + elRect.left, -rect.y + elRect.top) // 克隆一份数据 - const clone = svg.clone(); + const clone = svg.clone() // 恢复原先的大小和变换信息 - svg.size(origWidth, origHeight); - draw.transform(origTransform); + svg.size(origWidth, origHeight) + draw.transform(origTransform) return { svg: clone, // 思维导图图形的整体svg元素,包括:svg(画布容器)、g(实际的思维导图组) svgHTML: clone.svg(), // svg字符串 rect: { ...rect, // 思维导图图形未缩放时的位置尺寸等信息 - ratio: rect.width / rect.height, // 思维导图图形的宽高比 + ratio: rect.width / rect.height // 思维导图图形的宽高比 }, origWidth, // 画布宽度 origHeight, // 画布高度 scaleX: origTransform.scaleX, // 思维导图图形的水平缩放值 - scaleY: origTransform.scaleY, // 思维导图图形的垂直缩放值 - }; + scaleY: origTransform.scaleY // 思维导图图形的垂直缩放值 + } } /** @@ -71,57 +71,57 @@ class MiniMap { */ calculationMiniMap(boxWidth, boxHeight) { let { svgHTML, rect, origWidth, origHeight, scaleX, scaleY } = - this.getMiniMap(); + this.getMiniMap() // 计算数据 - let boxRatio = boxWidth / boxHeight; - let actWidth = 0; - let actHeight = 0; + let boxRatio = boxWidth / boxHeight + let actWidth = 0 + let actHeight = 0 if (boxRatio > rect.ratio) { // 高度以box为准,缩放宽度 - actHeight = boxHeight; - actWidth = rect.ratio * actHeight; + actHeight = boxHeight + actWidth = rect.ratio * actHeight } else { // 宽度以box为准,缩放高度 - actWidth = boxWidth; - actHeight = actWidth / rect.ratio; + actWidth = boxWidth + actHeight = actWidth / rect.ratio } // svg图形的缩放及位置 - let miniMapBoxScale = actWidth / rect.width; - let miniMapBoxLeft = (boxWidth - actWidth) / 2; - let miniMapBoxTop = (boxHeight - actHeight) / 2; + let miniMapBoxScale = actWidth / rect.width + let miniMapBoxLeft = (boxWidth - actWidth) / 2 + let miniMapBoxTop = (boxHeight - actHeight) / 2 // 视口框大小及位置 - let _rectX = rect.x - (rect.width * scaleX - rect.width) / 2; - let _rectX2 = rect.x2 + (rect.width * scaleX - rect.width) / 2; - let _rectY = rect.y - (rect.height * scaleY - rect.height) / 2; - let _rectY2 = rect.y2 + (rect.height * scaleY - rect.height) / 2; - let _rectWidth = rect.width * scaleX; - let _rectHeight = rect.height * scaleY; + let _rectX = rect.x - (rect.width * scaleX - rect.width) / 2 + let _rectX2 = rect.x2 + (rect.width * scaleX - rect.width) / 2 + let _rectY = rect.y - (rect.height * scaleY - rect.height) / 2 + let _rectY2 = rect.y2 + (rect.height * scaleY - rect.height) / 2 + let _rectWidth = rect.width * scaleX + let _rectHeight = rect.height * scaleY let viewBoxStyle = { left: 0, top: 0, right: 0, - bottom: 0, - }; + bottom: 0 + } viewBoxStyle.left = - Math.max(0, (-_rectX / _rectWidth) * actWidth) + miniMapBoxLeft + "px"; + Math.max(0, (-_rectX / _rectWidth) * actWidth) + miniMapBoxLeft + 'px' viewBoxStyle.right = Math.max(0, ((_rectX2 - origWidth) / _rectWidth) * actWidth) + miniMapBoxLeft + - "px"; + 'px' viewBoxStyle.top = - Math.max(0, (-_rectY / _rectHeight) * actHeight) + miniMapBoxTop + "px"; + Math.max(0, (-_rectY / _rectHeight) * actHeight) + miniMapBoxTop + 'px' viewBoxStyle.bottom = Math.max(0, ((_rectY2 - origHeight) / _rectHeight) * actHeight) + miniMapBoxTop + - "px"; + 'px' return { svgHTML, // 小地图html viewBoxStyle, // 视图框的位置信息 miniMapBoxScale, // 视图框的缩放值 miniMapBoxLeft, // 视图框的left值 - miniMapBoxTop, // 视图框的top值 - }; + miniMapBoxTop // 视图框的top值 + } } /** @@ -131,17 +131,17 @@ class MiniMap { * @Desc: 小地图鼠标按下事件 */ onMousedown(e) { - this.isMousedown = true; + this.isMousedown = true this.mousedownPos = { x: e.clientX, - y: e.clientY, - }; + y: e.clientY + } // 保存视图当前的偏移量 - let transformData = this.mindMap.view.getTransformData(); + let transformData = this.mindMap.view.getTransformData() this.startViewPos = { x: transformData.state.x, - y: transformData.state.y, - }; + y: transformData.state.y + } } /** @@ -152,13 +152,13 @@ class MiniMap { */ onMousemove(e, sensitivityNum = 5) { if (!this.isMousedown) { - return; + return } - let ox = e.clientX - this.mousedownPos.x; - let oy = e.clientY - this.mousedownPos.y; + let ox = e.clientX - this.mousedownPos.x + let oy = e.clientY - this.mousedownPos.y // 在视图最初偏移量上累加更新量 - this.mindMap.view.translateXTo(ox * sensitivityNum + this.startViewPos.x); - this.mindMap.view.translateYTo(oy * sensitivityNum + this.startViewPos.y); + this.mindMap.view.translateXTo(ox * sensitivityNum + this.startViewPos.x) + this.mindMap.view.translateYTo(oy * sensitivityNum + this.startViewPos.y) } /** @@ -168,8 +168,8 @@ class MiniMap { * @Desc: 小地图鼠标松开事件 */ onMouseup() { - this.isMousedown = false; + this.isMousedown = false } } -export default MiniMap; +export default MiniMap diff --git a/simple-mind-map/src/Node.js b/simple-mind-map/src/Node.js index 364a53d6..5d8d42d8 100644 --- a/simple-mind-map/src/Node.js +++ b/simple-mind-map/src/Node.js @@ -1,529 +1,543 @@ import Style from './Style' import Shape from './Shape' -import { - resizeImgSize, - asyncRun -} from './utils' -import { - Image, - SVG, - Circle, - A, - G, - Rect, - Text -} from '@svgdotjs/svg.js' +import { resizeImgSize, asyncRun } from './utils' +import { Image, SVG, Circle, A, G, Rect, Text } from '@svgdotjs/svg.js' import btnsSvg from './svg/btns' import iconsSvg from './svg/icons' -/** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-06 11:26:00 +/** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-06 11:26:00 * @Desc: 节点类 */ class Node { - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-06 11:26:17 - * @Desc: 构造函数 - */ - constructor(opt = {}) { - // 节点数据 - this.nodeData = this.handleData(opt.data || {}) - // id - this.uid = opt.uid - // 控制实例 - this.mindMap = opt.mindMap - // 渲染实例 - this.renderer = opt.renderer - // 渲染器 - this.draw = opt.draw || null - // 主题配置 - this.themeConfig = this.mindMap.themeConfig - // 样式实例 - this.style = new Style(this, this.themeConfig) - // 形状实例 - this.shapeInstance = new Shape(this) - this.shapePadding = { - paddingX: 0, - paddingY: 0 - } - // 是否是根节点 - this.isRoot = opt.isRoot === undefined ? false : opt.isRoot - // 是否是概要节点 - this.isGeneralization = opt.isGeneralization === undefined ? false : opt.isGeneralization - this.generalizationBelongNode = null - // 节点层级 - this.layerIndex = opt.layerIndex === undefined ? 0 : opt.layerIndex - // 节点宽 - this.width = opt.width || 0 - // 节点高 - this.height = opt.height || 0 - // left - this._left = opt.left || 0 - // top - this._top = opt.top || 0 - // 自定义位置 - this.customLeft = opt.data.data.customLeft || undefined - this.customTop = opt.data.data.customTop || undefined - // 是否正在拖拽中 - this.isDrag = false - // 父节点 - this.parent = opt.parent || null - // 子节点 - this.children = opt.children || [] - // 节点内容的容器 - this.group = null - // 节点内容对象 - this._imgData = null - this._iconData = null - this._textData = null - this._hyperlinkData = null - this._tagData = null - this._noteData = null - this.noteEl = null - this._expandBtn = null - this._lines = [] - this._generalizationLine = null - this._generalizationNode = null - // 尺寸信息 - this._rectInfo = { - imgContentWidth: 0, - imgContentHeight: 0, - textContentWidth: 0, - textContentHeight: 0 - } - // 概要节点的宽高 - this._generalizationNodeWidth = 0 - this._generalizationNodeHeight = 0 - // 各种文字信息的间距 - this.textContentItemMargin = this.mindMap.opt.textContentMargin - // 图片和文字节点的间距 - this.blockContentMargin = this.mindMap.opt.imgTextMargin - // 展开收缩按钮尺寸 - this.expandBtnSize = this.mindMap.opt.expandBtnSize - // 初始渲染 - this.initRender = true - // 初始化 - // this.createNodeData() - this.getSize() + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-06 11:26:17 + * @Desc: 构造函数 + */ + constructor(opt = {}) { + // 节点数据 + this.nodeData = this.handleData(opt.data || {}) + // id + this.uid = opt.uid + // 控制实例 + this.mindMap = opt.mindMap + // 渲染实例 + this.renderer = opt.renderer + // 渲染器 + this.draw = opt.draw || null + // 主题配置 + this.themeConfig = this.mindMap.themeConfig + // 样式实例 + this.style = new Style(this, this.themeConfig) + // 形状实例 + this.shapeInstance = new Shape(this) + this.shapePadding = { + paddingX: 0, + paddingY: 0 } - - // 支持自定义位置 - get left() { - return this.customLeft || this._left + // 是否是根节点 + this.isRoot = opt.isRoot === undefined ? false : opt.isRoot + // 是否是概要节点 + this.isGeneralization = + opt.isGeneralization === undefined ? false : opt.isGeneralization + this.generalizationBelongNode = null + // 节点层级 + this.layerIndex = opt.layerIndex === undefined ? 0 : opt.layerIndex + // 节点宽 + this.width = opt.width || 0 + // 节点高 + this.height = opt.height || 0 + // left + this._left = opt.left || 0 + // top + this._top = opt.top || 0 + // 自定义位置 + this.customLeft = opt.data.data.customLeft || undefined + this.customTop = opt.data.data.customTop || undefined + // 是否正在拖拽中 + this.isDrag = false + // 父节点 + this.parent = opt.parent || null + // 子节点 + this.children = opt.children || [] + // 节点内容的容器 + this.group = null + // 节点内容对象 + this._imgData = null + this._iconData = null + this._textData = null + this._hyperlinkData = null + this._tagData = null + this._noteData = null + this.noteEl = null + this._expandBtn = null + this._lines = [] + this._generalizationLine = null + this._generalizationNode = null + // 尺寸信息 + this._rectInfo = { + imgContentWidth: 0, + imgContentHeight: 0, + textContentWidth: 0, + textContentHeight: 0 } + // 概要节点的宽高 + this._generalizationNodeWidth = 0 + this._generalizationNodeHeight = 0 + // 各种文字信息的间距 + this.textContentItemMargin = this.mindMap.opt.textContentMargin + // 图片和文字节点的间距 + this.blockContentMargin = this.mindMap.opt.imgTextMargin + // 展开收缩按钮尺寸 + this.expandBtnSize = this.mindMap.opt.expandBtnSize + // 初始渲染 + this.initRender = true + // 初始化 + // this.createNodeData() + this.getSize() + } - set left(val) { - this._left = val + // 支持自定义位置 + get left() { + return this.customLeft || this._left + } + + set left(val) { + this._left = val + } + + get top() { + return this.customTop || this._top + } + + set top(val) { + this._top = val + } + + /** + * @Author: 王林 + * @Date: 2021-07-12 07:40:47 + * @Desc: 更新主题配置 + */ + updateThemeConfig() { + // 主题配置 + this.themeConfig = this.mindMap.themeConfig + // 样式实例 + this.style.updateThemeConfig(this.themeConfig) + } + + /** + * @Author: 王林 + * @Date: 2021-07-05 23:11:39 + * @Desc: 复位部分布局时会重新设置的数据 + */ + reset() { + this.children = [] + this.parent = null + this.isRoot = false + this.layerIndex = 0 + this.left = 0 + this.top = 0 + } + + /** + * @Author: 王林 + * @Date: 2021-06-20 10:12:31 + * @Desc: 处理数据 + */ + handleData(data) { + data.data.expand = data.data.expand === false ? false : true + data.data.isActive = data.data.isActive === true ? true : false + data.children = data.children || [] + return data + } + + /** + * javascript comment + * @Author: 王林25 + * @Date: 2022-08-02 19:53:40 + * @Desc: 检查节点是否存在自定义数据 + */ + hasCustomPosition() { + return this.customLeft !== undefined && this.customTop !== undefined + } + + /** + * javascript comment + * @Author: 王林25 + * @Date: 2022-08-04 09:06:56 + * @Desc: 检查节点是否存在自定义位置的祖先节点 + */ + ancestorHasCustomPosition() { + let node = this + while (node) { + if (node.hasCustomPosition()) { + return true + } + node = node.parent } + return false + } - get top() { - return this.customTop || this._top + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-06 15:55:04 + * @Desc: 添加子节点 + */ + addChildren(node) { + this.children.push(node) + } + + /** + * @Author: 王林 + * @Date: 2021-07-06 22:08:09 + * @Desc: 创建节点的各个内容对象数据 + */ + createNodeData() { + this._imgData = this.createImgNode() + this._iconData = this.createIconNode() + this._textData = this.createTextNode() + this._hyperlinkData = this.createHyperlinkNode() + this._tagData = this.createTagNode() + this._noteData = this.createNoteNode() + this.createGeneralizationNode() + } + + /** + * @Author: 王林 + * @Date: 2021-07-10 09:20:02 + * @Desc: 解绑所有事件 + */ + removeAllEvent() { + if (this._noteData) { + this._noteData.node.off(['mouseover', 'mouseout']) } - - set top(val) { - this._top = val + if (this._expandBtn) { + this._expandBtn.off(['mouseover', 'mouseout', 'click']) } - - /** - * @Author: 王林 - * @Date: 2021-07-12 07:40:47 - * @Desc: 更新主题配置 - */ - updateThemeConfig() { - // 主题配置 - this.themeConfig = this.mindMap.themeConfig - // 样式实例 - this.style.updateThemeConfig(this.themeConfig) + if (this.group) { + this.group.off([ + 'click', + 'dblclick', + 'contextmenu', + 'mousedown', + 'mouseup' + ]) } + } - /** - * @Author: 王林 - * @Date: 2021-07-05 23:11:39 - * @Desc: 复位部分布局时会重新设置的数据 - */ - reset() { - this.children = [] - this.parent = null - this.isRoot = false - this.layerIndex = 0 - this.left = 0 - this.top = 0 + /** + * @Author: 王林 + * @Date: 2021-07-07 21:27:24 + * @Desc: 移除节点内容 + */ + removeAllNode() { + // 节点内的内容 + ;[ + this._imgData, + this._iconData, + this._textData, + this._hyperlinkData, + this._tagData, + this._noteData + ].forEach(item => { + if (item && item.node) item.node.remove() + }) + this._imgData = null + this._iconData = null + this._textData = null + this._hyperlinkData = null + this._tagData = null + this._noteData = null + // 展开收缩按钮 + if (this._expandBtn) { + this._expandBtn.remove() + this._expandBtn = null } - - /** - * @Author: 王林 - * @Date: 2021-06-20 10:12:31 - * @Desc: 处理数据 - */ - handleData(data) { - data.data.expand = data.data.expand === false ? false : true - data.data.isActive = data.data.isActive === true ? true : false - data.children = data.children || [] - return data + // 组 + if (this.group) { + this.group.clear() + this.group.remove() + this.group = null } + // 概要 + this.removeGeneralization() + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2022-08-02 19:53:40 - * @Desc: 检查节点是否存在自定义数据 - */ - hasCustomPosition() { - return this.customLeft !== undefined && this.customTop !== undefined + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-09 09:46:23 + * @Desc: 计算节点的宽高 + */ + getSize() { + this.removeAllNode() + this.createNodeData() + let { width, height } = this.getNodeRect() + // 判断节点尺寸是否有变化 + let changed = this.width !== width || this.height !== height + this.width = width + this.height = height + return changed + } + + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-06 14:52:17 + * @Desc: 计算节点尺寸信息 + */ + getNodeRect() { + // 宽高 + let imgContentWidth = 0 + let imgContentHeight = 0 + let textContentWidth = 0 + let textContentHeight = 0 + // 存在图片 + if (this._imgData) { + this._rectInfo.imgContentWidth = imgContentWidth = this._imgData.width + this._rectInfo.imgContentHeight = imgContentHeight = this._imgData.height } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2022-08-04 09:06:56 - * @Desc: 检查节点是否存在自定义位置的祖先节点 - */ - ancestorHasCustomPosition() { - let node = this - while(node) { - if (node.hasCustomPosition()) { - return true - } - node = node.parent - } - return false + // 图标 + if (this._iconData.length > 0) { + textContentWidth += this._iconData.reduce((sum, cur) => { + textContentHeight = Math.max(textContentHeight, cur.height) + return (sum += cur.width + this.textContentItemMargin) + }, 0) } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-06 15:55:04 - * @Desc: 添加子节点 - */ - addChildren(node) { - this.children.push(node) + // 文字 + if (this._textData) { + textContentWidth += this._textData.width + textContentHeight = Math.max(textContentHeight, this._textData.height) } - - /** - * @Author: 王林 - * @Date: 2021-07-06 22:08:09 - * @Desc: 创建节点的各个内容对象数据 - */ - createNodeData() { - this._imgData = this.createImgNode() - this._iconData = this.createIconNode() - this._textData = this.createTextNode() - this._hyperlinkData = this.createHyperlinkNode() - this._tagData = this.createTagNode() - this._noteData = this.createNoteNode() - this.createGeneralizationNode() + // 超链接 + if (this._hyperlinkData) { + textContentWidth += this._hyperlinkData.width + textContentHeight = Math.max( + textContentHeight, + this._hyperlinkData.height + ) } - - /** - * @Author: 王林 - * @Date: 2021-07-10 09:20:02 - * @Desc: 解绑所有事件 - */ - removeAllEvent() { - if (this._noteData) { - this._noteData.node.off(['mouseover', 'mouseout']) - } - if (this._expandBtn) { - this._expandBtn.off(['mouseover', 'mouseout', 'click']) - } - if (this.group) { - this.group.off(['click', 'dblclick', 'contextmenu', 'mousedown', 'mouseup']) - } + // 标签 + if (this._tagData.length > 0) { + textContentWidth += this._tagData.reduce((sum, cur) => { + textContentHeight = Math.max(textContentHeight, cur.height) + return (sum += cur.width + this.textContentItemMargin) + }, 0) } - - /** - * @Author: 王林 - * @Date: 2021-07-07 21:27:24 - * @Desc: 移除节点内容 - */ - removeAllNode() { - // 节点内的内容 - ;[this._imgData, this._iconData, this._textData, this._hyperlinkData, this._tagData, this._noteData].forEach((item) => { - if (item && item.node) item.node.remove() - }) - this._imgData = null - this._iconData = null - this._textData = null - this._hyperlinkData = null - this._tagData = null - this._noteData = null - // 展开收缩按钮 - if (this._expandBtn) { - this._expandBtn.remove() - this._expandBtn = null - } - // 组 - if (this.group) { - this.group.clear() - this.group.remove() - this.group = null - } - // 概要 - this.removeGeneralization() + // 备注 + if (this._noteData) { + textContentWidth += this._noteData.width + textContentHeight = Math.max(textContentHeight, this._noteData.height) } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-09 09:46:23 - * @Desc: 计算节点的宽高 - */ - getSize() { - this.removeAllNode() - this.createNodeData() - let { - width, - height - } = this.getNodeRect() - // 判断节点尺寸是否有变化 - let changed = this.width !== width || this.height !== height - this.width = width - this.height = height - return changed + // 文字内容部分的尺寸 + this._rectInfo.textContentWidth = textContentWidth + this._rectInfo.textContentHeight = textContentHeight + // 间距 + let margin = + imgContentHeight > 0 && textContentHeight > 0 + ? this.blockContentMargin + : 0 + let { paddingX, paddingY } = this.getPaddingVale() + // 纯内容宽高 + let _width = Math.max(imgContentWidth, textContentWidth) + let _height = imgContentHeight + textContentHeight + // 计算节点形状需要的附加内边距 + let { paddingX: shapePaddingX, paddingY: shapePaddingY } = + this.shapeInstance.getShapePadding(_width, _height, paddingX, paddingY) + this.shapePadding.paddingX = shapePaddingX + this.shapePadding.paddingY = shapePaddingY + return { + width: _width + paddingX * 2 + shapePaddingX * 2, + height: _height + paddingY * 2 + margin + shapePaddingY * 2 } + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-06 14:52:17 - * @Desc: 计算节点尺寸信息 - */ - getNodeRect() { - // 宽高 - let imgContentWidth = 0 - let imgContentHeight = 0 - let textContentWidth = 0 - let textContentHeight = 0 - // 存在图片 - if (this._imgData) { - this._rectInfo.imgContentWidth = imgContentWidth = this._imgData.width - this._rectInfo.imgContentHeight = imgContentHeight = this._imgData.height - } - // 图标 - if (this._iconData.length > 0) { - textContentWidth += this._iconData.reduce((sum, cur) => { - textContentHeight = Math.max(textContentHeight, cur.height) - return sum += cur.width + this.textContentItemMargin - }, 0) - } - // 文字 - if (this._textData) { - textContentWidth += this._textData.width - textContentHeight = Math.max(textContentHeight, this._textData.height) - } - // 超链接 - if (this._hyperlinkData) { - textContentWidth += this._hyperlinkData.width - textContentHeight = Math.max(textContentHeight, this._hyperlinkData.height) - } - // 标签 - if (this._tagData.length > 0) { - textContentWidth += this._tagData.reduce((sum, cur) => { - textContentHeight = Math.max(textContentHeight, cur.height) - return sum += cur.width + this.textContentItemMargin - }, 0) - } - // 备注 - if (this._noteData) { - textContentWidth += this._noteData.width - textContentHeight = Math.max(textContentHeight, this._noteData.height) - } - // 文字内容部分的尺寸 - this._rectInfo.textContentWidth = textContentWidth - this._rectInfo.textContentHeight = textContentHeight - // 间距 - let margin = imgContentHeight > 0 && textContentHeight > 0 ? this.blockContentMargin : 0 - let { paddingX, paddingY } = this.getPaddingVale() - // 纯内容宽高 - let _width = Math.max(imgContentWidth, textContentWidth) - let _height = imgContentHeight + textContentHeight - // 计算节点形状需要的附加内边距 - let { paddingX: shapePaddingX, paddingY: shapePaddingY } = this.shapeInstance.getShapePadding(_width, _height, paddingX, paddingY) - this.shapePadding.paddingX = shapePaddingX - this.shapePadding.paddingY = shapePaddingY - return { - width: _width + paddingX * 2 + shapePaddingX * 2, - height: _height + paddingY * 2 + margin + shapePaddingY * 2 - } + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-09 14:06:17 + * @Desc: 创建图片节点 + */ + createImgNode() { + let img = this.nodeData.data.image + if (!img) { + return } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-09 14:06:17 - * @Desc: 创建图片节点 - */ - createImgNode() { - let img = this.nodeData.data.image - if (!img) { - return - } - let imgSize = this.getImgShowSize() - let node = new Image().load(img).size(...imgSize) - if (this.nodeData.data.imageTitle) { - node.attr('title', this.nodeData.data.imageTitle) - } - node.on('dblclick', (e) => { - this.mindMap.emit('node_img_dblclick', this, e) - }) - return { - node, - width: imgSize[0], - height: imgSize[1] - } + let imgSize = this.getImgShowSize() + let node = new Image().load(img).size(...imgSize) + if (this.nodeData.data.imageTitle) { + node.attr('title', this.nodeData.data.imageTitle) } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-09 10:12:51 - * @Desc: 获取图片显示宽高 - */ - getImgShowSize() { - return resizeImgSize(this.nodeData.data.imageSize.width, this.nodeData.data.imageSize.height, this.themeConfig.imgMaxWidth, this.themeConfig.imgMaxHeight) + node.on('dblclick', e => { + this.mindMap.emit('node_img_dblclick', this, e) + }) + return { + node, + width: imgSize[0], + height: imgSize[1] } + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-09 14:10:48 - * @Desc: 创建icon节点 - */ - createIconNode() { - let _data = this.nodeData.data - if (!_data.icon || _data.icon.length <= 0) { - return [] - } - let iconSize = this.themeConfig.iconSize - return _data.icon.map((item) => { - return { - node: SVG(iconsSvg.getNodeIconListIcon(item)).size(iconSize, iconSize), - width: iconSize, - height: iconSize - } - }) + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-09 10:12:51 + * @Desc: 获取图片显示宽高 + */ + getImgShowSize() { + return resizeImgSize( + this.nodeData.data.imageSize.width, + this.nodeData.data.imageSize.height, + this.themeConfig.imgMaxWidth, + this.themeConfig.imgMaxHeight + ) + } + + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-09 14:10:48 + * @Desc: 创建icon节点 + */ + createIconNode() { + let _data = this.nodeData.data + if (!_data.icon || _data.icon.length <= 0) { + return [] } + let iconSize = this.themeConfig.iconSize + return _data.icon.map(item => { + return { + node: SVG(iconsSvg.getNodeIconListIcon(item)).size(iconSize, iconSize), + width: iconSize, + height: iconSize + } + }) + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-09 14:08:56 - * @Desc: 创建文本节点 - */ - createTextNode() { - let g = new G() - let fontSize = this.getStyle('fontSize', this.isRoot, this.nodeData.data.isActive) - let lineHeight = this.getStyle('lineHeight', this.isRoot, this.nodeData.data.isActive) - this.nodeData.data.text.split(/\n/img).forEach((item, index) => { - let node = new Text().text(item) - this.style.text(node) - node.y(fontSize * lineHeight * index) - g.add(node) - }) - let { - width, - height - } = g.bbox() - return { - node: g, - width, - height - } + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-09 14:08:56 + * @Desc: 创建文本节点 + */ + createTextNode() { + let g = new G() + let fontSize = this.getStyle( + 'fontSize', + this.isRoot, + this.nodeData.data.isActive + ) + let lineHeight = this.getStyle( + 'lineHeight', + this.isRoot, + this.nodeData.data.isActive + ) + this.nodeData.data.text.split(/\n/gim).forEach((item, index) => { + let node = new Text().text(item) + this.style.text(node) + node.y(fontSize * lineHeight * index) + g.add(node) + }) + let { width, height } = g.bbox() + return { + node: g, + width, + height } + } - /** - * @Author: 王林 - * @Date: 2021-06-20 15:28:54 - * @Desc: 创建超链接节点 - */ - createHyperlinkNode() { - let { hyperlink, hyperlinkTitle } = this.nodeData.data - if (!hyperlink) { - return - } - let iconSize = this.themeConfig.iconSize - let node = new SVG() - // 超链接节点 - let a = new A().to(hyperlink).target('_blank') - a.node.addEventListener('click', (e) => { - e.stopPropagation() - }) - if (hyperlinkTitle) { - a.attr('title', hyperlinkTitle) - } - // 添加一个透明的层,作为鼠标区域 - a.rect(iconSize, iconSize).fill({ color: 'transparent' }) - // 超链接图标 - let iconNode = SVG(iconsSvg.hyperlink).size(iconSize, iconSize) - this.style.iconNode(iconNode) - a.add(iconNode) - node.add(a) - return { - node, - width: iconSize, - height: iconSize - } + /** + * @Author: 王林 + * @Date: 2021-06-20 15:28:54 + * @Desc: 创建超链接节点 + */ + createHyperlinkNode() { + let { hyperlink, hyperlinkTitle } = this.nodeData.data + if (!hyperlink) { + return } - - /** - * @Author: 王林 - * @Date: 2021-06-20 19:49:15 - * @Desc: 创建标签节点 - */ - createTagNode() { - let tagData = this.nodeData.data.tag - if (!tagData || tagData.length <= 0) { - return [] - } - let nodes = [] - tagData.slice(0, this.mindMap.opt.maxTag).forEach((item, index) => { - let tag = new G() - // 标签文本 - let text = new Text().text(item).x(8).cy(10) - this.style.tagText(text, index) - let { - width, - height - } = text.bbox() - // 标签矩形 - let rect = new Rect().size(width + 16, 20) - this.style.tagRect(rect, index) - tag.add(rect).add(text) - nodes.push({ - node: tag, - width: width + 16, - height: 20 - }) - }) - return nodes + let iconSize = this.themeConfig.iconSize + let node = new SVG() + // 超链接节点 + let a = new A().to(hyperlink).target('_blank') + a.node.addEventListener('click', e => { + e.stopPropagation() + }) + if (hyperlinkTitle) { + a.attr('title', hyperlinkTitle) } + // 添加一个透明的层,作为鼠标区域 + a.rect(iconSize, iconSize).fill({ color: 'transparent' }) + // 超链接图标 + let iconNode = SVG(iconsSvg.hyperlink).size(iconSize, iconSize) + this.style.iconNode(iconNode) + a.add(iconNode) + node.add(a) + return { + node, + width: iconSize, + height: iconSize + } + } - /** - * @Author: 王林 - * @Date: 2021-06-20 21:19:36 - * @Desc: 创建备注节点 - */ - createNoteNode() { - if (!this.nodeData.data.note) { - return null - } - let iconSize = this.themeConfig.iconSize - let node = new SVG().attr('cursor', 'pointer') - // 透明的层,用来作为鼠标区域 - node.add(new Rect().size(iconSize, iconSize).fill({ color: 'transparent' })) - // 备注图标 - let iconNode = SVG(iconsSvg.note).size(iconSize, iconSize) - this.style.iconNode(iconNode) - node.add(iconNode) - // 备注tooltip - if (!this.mindMap.opt.customNoteContentShow) { - if (!this.noteEl) { - this.noteEl = document.createElement('div') - this.noteEl.style.cssText = ` + /** + * @Author: 王林 + * @Date: 2021-06-20 19:49:15 + * @Desc: 创建标签节点 + */ + createTagNode() { + let tagData = this.nodeData.data.tag + if (!tagData || tagData.length <= 0) { + return [] + } + let nodes = [] + tagData.slice(0, this.mindMap.opt.maxTag).forEach((item, index) => { + let tag = new G() + // 标签文本 + let text = new Text().text(item).x(8).cy(10) + this.style.tagText(text, index) + let { width } = text.bbox() + // 标签矩形 + let rect = new Rect().size(width + 16, 20) + this.style.tagRect(rect, index) + tag.add(rect).add(text) + nodes.push({ + node: tag, + width: width + 16, + height: 20 + }) + }) + return nodes + } + + /** + * @Author: 王林 + * @Date: 2021-06-20 21:19:36 + * @Desc: 创建备注节点 + */ + createNoteNode() { + if (!this.nodeData.data.note) { + return null + } + let iconSize = this.themeConfig.iconSize + let node = new SVG().attr('cursor', 'pointer') + // 透明的层,用来作为鼠标区域 + node.add(new Rect().size(iconSize, iconSize).fill({ color: 'transparent' })) + // 备注图标 + let iconNode = SVG(iconsSvg.note).size(iconSize, iconSize) + this.style.iconNode(iconNode) + node.add(iconNode) + // 备注tooltip + if (!this.mindMap.opt.customNoteContentShow) { + if (!this.noteEl) { + this.noteEl = document.createElement('div') + this.noteEl.style.cssText = ` position: absolute; padding: 10px; border-radius: 5px; @@ -531,791 +545,846 @@ class Node { display: none; background-color: #fff; ` - document.body.appendChild(this.noteEl) - } - this.noteEl.innerText = this.nodeData.data.note - } - node.on('mouseover', () => { - let { left, top } = node.node.getBoundingClientRect() - if (!this.mindMap.opt.customNoteContentShow) { - this.noteEl.style.left = left + 'px' - this.noteEl.style.top = top + iconSize + 'px' - this.noteEl.style.display = 'block' - } else { - this.mindMap.opt.customNoteContentShow.show(this.nodeData.data.note, left, top + iconSize) - } - }) - node.on('mouseout', () => { - if (!this.mindMap.opt.customNoteContentShow) { - this.noteEl.style.display = 'none' - } else { - this.mindMap.opt.customNoteContentShow.hide() - } - }) - return { - node, - width: iconSize, - height: iconSize - } + document.body.appendChild(this.noteEl) + } + this.noteEl.innerText = this.nodeData.data.note } - - /** - * javascript comment - * @Author: 王林 - * @Date: 2022-09-12 22:02:07 - * @Desc: 获取节点形状 - */ - getShape() { - return this.style.getStyle('shape', false, false) - } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-09 11:10:11 - * @Desc: 定位节点内容 - */ - layout() { - let { - width, - height, - textContentItemMargin - } = this - let { paddingY } = this.getPaddingVale() - paddingY += this.shapePadding.paddingY - // 创建组 - this.group = new G() - // 概要节点添加一个带所属节点id的类名 - if (this.isGeneralization && this.generalizationBelongNode) { - this.group.addClass('generalization_' + this.generalizationBelongNode.uid) - } - this.draw.add(this.group) - this.update(true) - // 节点形状 - const shape = this.getShape() - this.style[shape === 'rectangle' ? 'rect' : 'shape'](this.shapeInstance.createShape()) - // 图片节点 - let imgHeight = 0 - if (this._imgData) { - imgHeight = this._imgData.height - this.group.add(this._imgData.node) - this._imgData.node.cx(width / 2).y(paddingY) - } - // 内容节点 - let textContentNested = new G() - let textContentOffsetX = 0 - // icon - let iconNested = new G() - if (this._iconData && this._iconData.length > 0) { - let iconLeft = 0 - this._iconData.forEach((item) => { - item.node.x(textContentOffsetX + iconLeft).y((this._rectInfo.textContentHeight - item.height) / 2) - iconNested.add(item.node) - iconLeft += item.width + textContentItemMargin - }) - textContentNested.add(iconNested) - textContentOffsetX += iconLeft - } - // 文字 - if (this._textData) { - this._textData.node.x(textContentOffsetX).y(0) - textContentNested.add(this._textData.node) - textContentOffsetX += this._textData.width + textContentItemMargin - } - // 超链接 - if (this._hyperlinkData) { - this._hyperlinkData.node.x(textContentOffsetX).y((this._rectInfo.textContentHeight - this._hyperlinkData.height) / 2) - textContentNested.add(this._hyperlinkData.node) - textContentOffsetX += this._hyperlinkData.width + textContentItemMargin - } - // 标签 - let tagNested = new G() - if (this._tagData && this._tagData.length > 0) { - let tagLeft = 0 - this._tagData.forEach((item) => { - item.node.x(textContentOffsetX + tagLeft).y((this._rectInfo.textContentHeight - item.height) / 2) - tagNested.add(item.node) - tagLeft += item.width + textContentItemMargin - }) - textContentNested.add(tagNested) - textContentOffsetX += tagLeft - } - // 备注 - if (this._noteData) { - this._noteData.node.x(textContentOffsetX).y((this._rectInfo.textContentHeight - this._noteData.height) / 2) - textContentNested.add(this._noteData.node) - textContentOffsetX += this._noteData.width - } - // 文字内容整体 - textContentNested.translate( - width / 2 - textContentNested.bbox().width / 2, - imgHeight + paddingY + (imgHeight > 0 && this._rectInfo.textContentHeight > 0 ? this.blockContentMargin : 0) + node.on('mouseover', () => { + let { left, top } = node.node.getBoundingClientRect() + if (!this.mindMap.opt.customNoteContentShow) { + this.noteEl.style.left = left + 'px' + this.noteEl.style.top = top + iconSize + 'px' + this.noteEl.style.display = 'block' + } else { + this.mindMap.opt.customNoteContentShow.show( + this.nodeData.data.note, + left, + top + iconSize ) - this.group.add(textContentNested) - // 单击事件,选中节点 - this.group.on('click', (e) => { - this.mindMap.emit('node_click', this, e) - this.active(e) - }) - this.group.on('mousedown', (e) => { - e.stopPropagation() - this.mindMap.emit('node_mousedown', this, e) - }) - this.group.on('mouseup', (e) => { - e.stopPropagation() - this.mindMap.emit('node_mouseup', this, e) - }) - // 双击事件 - this.group.on('dblclick', (e) => { - if (this.mindMap.opt.readonly) { - return - } - e.stopPropagation() - this.mindMap.emit('node_dblclick', this, e) - }) - // 右键菜单事件 - this.group.on('contextmenu', (e) => { - if (this.mindMap.opt.readonly || this.isGeneralization) { - return - } - e.stopPropagation() - e.preventDefault() - if (this.nodeData.data.isActive) { - this.renderer.clearActive() - } - this.active(e) - this.mindMap.emit('node_contextmenu', e, this) - }) + } + }) + node.on('mouseout', () => { + if (!this.mindMap.opt.customNoteContentShow) { + this.noteEl.style.display = 'none' + } else { + this.mindMap.opt.customNoteContentShow.hide() + } + }) + return { + node, + width: iconSize, + height: iconSize } + } - /** - * @Author: 王林 - * @Date: 2021-07-10 16:44:22 - * @Desc: 激活节点 - */ - active(e) { - if (this.mindMap.opt.readonly) { - return - } - e && e.stopPropagation() - if (this.nodeData.data.isActive) { - return - } - this.mindMap.emit('before_node_active', this, this.renderer.activeNodeList) + /** + * javascript comment + * @Author: 王林 + * @Date: 2022-09-12 22:02:07 + * @Desc: 获取节点形状 + */ + getShape() { + return this.style.getStyle('shape', false, false) + } + + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-09 11:10:11 + * @Desc: 定位节点内容 + */ + layout() { + let { width, textContentItemMargin } = this + let { paddingY } = this.getPaddingVale() + paddingY += this.shapePadding.paddingY + // 创建组 + this.group = new G() + // 概要节点添加一个带所属节点id的类名 + if (this.isGeneralization && this.generalizationBelongNode) { + this.group.addClass('generalization_' + this.generalizationBelongNode.uid) + } + this.draw.add(this.group) + this.update(true) + // 节点形状 + const shape = this.getShape() + this.style[shape === 'rectangle' ? 'rect' : 'shape']( + this.shapeInstance.createShape() + ) + // 图片节点 + let imgHeight = 0 + if (this._imgData) { + imgHeight = this._imgData.height + this.group.add(this._imgData.node) + this._imgData.node.cx(width / 2).y(paddingY) + } + // 内容节点 + let textContentNested = new G() + let textContentOffsetX = 0 + // icon + let iconNested = new G() + if (this._iconData && this._iconData.length > 0) { + let iconLeft = 0 + this._iconData.forEach(item => { + item.node + .x(textContentOffsetX + iconLeft) + .y((this._rectInfo.textContentHeight - item.height) / 2) + iconNested.add(item.node) + iconLeft += item.width + textContentItemMargin + }) + textContentNested.add(iconNested) + textContentOffsetX += iconLeft + } + // 文字 + if (this._textData) { + this._textData.node.x(textContentOffsetX).y(0) + textContentNested.add(this._textData.node) + textContentOffsetX += this._textData.width + textContentItemMargin + } + // 超链接 + if (this._hyperlinkData) { + this._hyperlinkData.node + .x(textContentOffsetX) + .y((this._rectInfo.textContentHeight - this._hyperlinkData.height) / 2) + textContentNested.add(this._hyperlinkData.node) + textContentOffsetX += this._hyperlinkData.width + textContentItemMargin + } + // 标签 + let tagNested = new G() + if (this._tagData && this._tagData.length > 0) { + let tagLeft = 0 + this._tagData.forEach(item => { + item.node + .x(textContentOffsetX + tagLeft) + .y((this._rectInfo.textContentHeight - item.height) / 2) + tagNested.add(item.node) + tagLeft += item.width + textContentItemMargin + }) + textContentNested.add(tagNested) + textContentOffsetX += tagLeft + } + // 备注 + if (this._noteData) { + this._noteData.node + .x(textContentOffsetX) + .y((this._rectInfo.textContentHeight - this._noteData.height) / 2) + textContentNested.add(this._noteData.node) + textContentOffsetX += this._noteData.width + } + // 文字内容整体 + textContentNested.translate( + width / 2 - textContentNested.bbox().width / 2, + imgHeight + + paddingY + + (imgHeight > 0 && this._rectInfo.textContentHeight > 0 + ? this.blockContentMargin + : 0) + ) + this.group.add(textContentNested) + // 单击事件,选中节点 + this.group.on('click', e => { + this.mindMap.emit('node_click', this, e) + this.active(e) + }) + this.group.on('mousedown', e => { + e.stopPropagation() + this.mindMap.emit('node_mousedown', this, e) + }) + this.group.on('mouseup', e => { + e.stopPropagation() + this.mindMap.emit('node_mouseup', this, e) + }) + // 双击事件 + this.group.on('dblclick', e => { + if (this.mindMap.opt.readonly) { + return + } + e.stopPropagation() + this.mindMap.emit('node_dblclick', this, e) + }) + // 右键菜单事件 + this.group.on('contextmenu', e => { + if (this.mindMap.opt.readonly || this.isGeneralization) { + return + } + e.stopPropagation() + e.preventDefault() + if (this.nodeData.data.isActive) { this.renderer.clearActive() - this.mindMap.execCommand('SET_NODE_ACTIVE', this, true) - this.renderer.addActiveNode(this) - this.mindMap.emit('node_active', this, this.renderer.activeNodeList) - } + } + this.active(e) + this.mindMap.emit('node_contextmenu', e, this) + }) + } - /** - * @Author: 王林 - * @Date: 2021-07-04 20:20:09 - * @Desc: 渲染节点到画布,会移除旧的,创建新的 - */ - renderNode() { - // 连线 - this.renderLine() - this.removeAllEvent() - this.removeAllNode() - this.createNodeData() - this.layout() + /** + * @Author: 王林 + * @Date: 2021-07-10 16:44:22 + * @Desc: 激活节点 + */ + active(e) { + if (this.mindMap.opt.readonly) { + return } - - /** - * @Author: 王林 - * @Date: 2021-07-04 22:47:01 - * @Desc: 更新节点 - */ - update(layout = false) { - if (!this.group) { - return - } - // 需要移除展开收缩按钮 - if (this._expandBtn && this.nodeData.children.length <= 0) { - this.removeExpandBtn() - } else if (!this._expandBtn && this.nodeData.children.length > 0) {// 需要添加展开收缩按钮 - this.renderExpandBtn() - } else { - this.updateExpandBtnPos() - } - this.renderGeneralization() - let t = this.group.transform() - if (!layout) { - this.group.animate(300).translate(this.left - t.translateX, this.top - t.translateY) - } else { - this.group.translate(this.left - t.translateX, this.top - t.translateY) - } + e && e.stopPropagation() + if (this.nodeData.data.isActive) { + return } + this.mindMap.emit('before_node_active', this, this.renderer.activeNodeList) + this.renderer.clearActive() + this.mindMap.execCommand('SET_NODE_ACTIVE', this, true) + this.renderer.addActiveNode(this) + this.mindMap.emit('node_active', this, this.renderer.activeNodeList) + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-07 13:55:58 - * @Desc: 递归渲染 - */ - render(callback = () => {}) { - // 节点 - if (this.initRender) { - this.initRender = false - this.renderNode() - } else { - // 连线 - this.renderLine() - this.update() - } - // 子节点 - if (this.children && this.children.length && this.nodeData.data.expand !== false) { - let index = 0 - asyncRun(this.children.map((item) => { - return () =>{ - item.render(() => { - index++ - if (index >= this.children.length) { - callback() - } - }) - } - })) - } else { - callback() - } - // 手动插入的节点立即获得焦点并且开启编辑模式 - if (this.nodeData.inserting) { - delete this.nodeData.inserting - this.active() - this.mindMap.emit('node_dblclick', this) - } + /** + * @Author: 王林 + * @Date: 2021-07-04 20:20:09 + * @Desc: 渲染节点到画布,会移除旧的,创建新的 + */ + renderNode() { + // 连线 + this.renderLine() + this.removeAllEvent() + this.removeAllNode() + this.createNodeData() + this.layout() + } + + /** + * @Author: 王林 + * @Date: 2021-07-04 22:47:01 + * @Desc: 更新节点 + */ + update(layout = false) { + if (!this.group) { + return } - - /** - * @Author: 王林 - * @Date: 2021-07-10 09:24:55 - * @Desc: 递归删除 - */ - remove() { - this.initRender = true - this.removeAllEvent() - this.removeAllNode() - this.removeLine() - // 子节点 - if (this.children && this.children.length) { - asyncRun(this.children.map((item) => { - return () =>{ - item.remove() - } - })) - } + // 需要移除展开收缩按钮 + if (this._expandBtn && this.nodeData.children.length <= 0) { + this.removeExpandBtn() + } else if (!this._expandBtn && this.nodeData.children.length > 0) { + // 需要添加展开收缩按钮 + this.renderExpandBtn() + } else { + this.updateExpandBtnPos() } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-11-23 18:39:14 - * @Desc: 隐藏节点 - */ - hide() { - this.group.hide() - this.hideGeneralization() - if (this.parent) { - let index = this.parent.children.indexOf(this) - this.parent._lines[index].hide() - } - // 子节点 - if (this.children && this.children.length) { - asyncRun(this.children.map((item) => { - return () =>{ - item.hide() - } - })) - } + this.renderGeneralization() + let t = this.group.transform() + if (!layout) { + this.group + .animate(300) + .translate(this.left - t.translateX, this.top - t.translateY) + } else { + this.group.translate(this.left - t.translateX, this.top - t.translateY) } + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-11-23 18:39:14 - * @Desc: 显示节点 - */ - show() { - if (!this.group) { - return; - } - this.group.show() - this.showGeneralization() - if (this.parent) { - let index = this.parent.children.indexOf(this) - this.parent._lines[index] && this.parent._lines[index].show() - } - // 子节点 - if (this.children && this.children.length) { - asyncRun(this.children.map((item) => { - return () =>{ - item.show() - } - })) - } + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-07 13:55:58 + * @Desc: 递归渲染 + */ + render(callback = () => {}) { + // 节点 + if (this.initRender) { + this.initRender = false + this.renderNode() + } else { + // 连线 + this.renderLine() + this.update() } - - /** - * @Author: 王林 - * @Date: 2021-04-10 22:01:53 - * @Desc: 连线 - */ - renderLine(deep = false) { - if (this.nodeData.data.expand === false) { - return - } - let childrenLen = this.nodeData.children.length - if (childrenLen > this._lines.length) { - // 创建缺少的线 - new Array(childrenLen - this._lines.length).fill(0).forEach(() => { - this._lines.push(this.draw.path()) + // 子节点 + if ( + this.children && + this.children.length && + this.nodeData.data.expand !== false + ) { + let index = 0 + asyncRun( + this.children.map(item => { + return () => { + item.render(() => { + index++ + if (index >= this.children.length) { + callback() + } }) - } else if (childrenLen < this._lines.length) { - // 删除多余的线 - this._lines.slice(childrenLen).forEach((line) => { - line.remove() - }) - this._lines = this._lines.slice(0, childrenLen) - } - // 画线 - this.renderer.layout.renderLine(this, this._lines, (line, node) => { - // 添加样式 - this.styleLine(line, node) - }, this.style.getStyle('lineStyle', true)) - // 子级的连线也需要更新 - if (deep && this.children && this.children.length > 0) { - this.children.forEach((item) => { - item.renderLine(deep) - }) - } - } - - /** - * javascript comment - * @Author: flydreame - * @Date: 2022-09-17 12:41:29 - * @Desc: 设置连线样式 - */ - styleLine(line, node) { - let width = node.getSelfInhertStyle('lineWidth') || node.getStyle('lineWidth', true) - let color = node.getSelfInhertStyle('lineColor') || node.getStyle('lineColor', true) - let dasharray = node.getSelfInhertStyle('lineDasharray') || node.getStyle('lineDasharray', true) - this.style.line(line, { - width, - color, - dasharray, + } }) + ) + } else { + callback() } + // 手动插入的节点立即获得焦点并且开启编辑模式 + if (this.nodeData.inserting) { + delete this.nodeData.inserting + this.active() + this.mindMap.emit('node_dblclick', this) + } + } - /** - * @Author: 王林 - * @Date: 2021-07-10 16:40:21 - * @Desc: 移除连线 - */ - removeLine() { - this._lines.forEach((line) => { - line.remove() + /** + * @Author: 王林 + * @Date: 2021-07-10 09:24:55 + * @Desc: 递归删除 + */ + remove() { + this.initRender = true + this.removeAllEvent() + this.removeAllNode() + this.removeLine() + // 子节点 + if (this.children && this.children.length) { + asyncRun( + this.children.map(item => { + return () => { + item.remove() + } }) - this._lines = [] + ) } + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2022-08-01 09:27:30 - * @Desc: 检查是否存在概要 - */ - checkHasGeneralization() { - return !!this.nodeData.data.generalization + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-11-23 18:39:14 + * @Desc: 隐藏节点 + */ + hide() { + this.group.hide() + this.hideGeneralization() + if (this.parent) { + let index = this.parent.children.indexOf(this) + this.parent._lines[index].hide() } - - /** - * @Author: 王林 - * @Date: 2022-07-31 09:41:28 - * @Desc: 创建概要节点 - */ - createGeneralizationNode() { - if (this.isGeneralization || !this.checkHasGeneralization()) { - return - } - if (!this._generalizationLine) { - this._generalizationLine = this.draw.path() - } - if (!this._generalizationNode) { - this._generalizationNode = new Node({ - data: { - data: this.nodeData.data.generalization - }, - uid: this.mindMap.uid++, - renderer: this.renderer, - mindMap: this.mindMap, - draw: this.draw, - isGeneralization: true - }) - this._generalizationNodeWidth = this._generalizationNode.width - this._generalizationNodeHeight = this._generalizationNode.height - this._generalizationNode.generalizationBelongNode = this - if (this.nodeData.data.generalization.isActive) { - this.renderer.addActiveNode(this._generalizationNode) - } - } - } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2022-08-01 15:38:52 - * @Desc: 更新概要节点 - */ - updateGeneralization() { - this.removeGeneralization() - this.createGeneralizationNode() - } - - /** - * @Author: 王林 - * @Date: 2022-07-30 08:35:51 - * @Desc: 渲染概要节点 - */ - renderGeneralization() { - if (this.isGeneralization) { - return - } - if (!this.checkHasGeneralization()) { - this.removeGeneralization() - this._generalizationNodeWidth = 0 - this._generalizationNodeHeight = 0 - return - } - if (this.nodeData.data.expand === false) { - this.removeGeneralization() - return - } - this.createGeneralizationNode() - this.renderer.layout.renderGeneralization(this, this._generalizationLine, this._generalizationNode) - this.style.generalizationLine(this._generalizationLine) - this._generalizationNode.render() - } - - /** - * @Author: 王林 - * @Date: 2022-07-30 13:11:27 - * @Desc: 删除概要节点 - */ - removeGeneralization() { - if (this._generalizationLine) { - this._generalizationLine.remove() - this._generalizationLine = null - } - if (this._generalizationNode) { - // 删除概要节点时要同步从激活节点里删除 - this.renderer.removeActiveNode(this._generalizationNode) - this._generalizationNode.remove() - this._generalizationNode = null - } - // hack修复当激活一个节点时创建概要,然后立即激活创建的概要节点后会重复创建概要节点并且无法删除的问题 - if (this.generalizationBelongNode) { - this.draw.find('.generalization_' + this.generalizationBelongNode.uid).remove() - } - } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2022-08-01 09:56:46 - * @Desc: 隐藏概要节点 - */ - hideGeneralization() { - if (this._generalizationLine) { - this._generalizationLine.hide() - } - if (this._generalizationNode) { - this._generalizationNode.hide() - } - } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2022-08-01 09:57:42 - * @Desc: 显示概要节点 - */ - showGeneralization() { - if (this._generalizationLine) { - this._generalizationLine.show() - } - if (this._generalizationNode) { - this._generalizationNode.show() - } - } - - /** - * @Author: 王林 - * @Date: 2021-07-10 17:59:14 - * @Desc: 创建或更新展开收缩按钮内容 - */ - updateExpandBtnNode() { - if (this._expandBtn) { - this._expandBtn.clear() - } - let iconSvg - if (this.nodeData.data.expand === false) { - iconSvg = btnsSvg.open - } else { - iconSvg = btnsSvg.close - } - let node = SVG(iconSvg).size(this.expandBtnSize, this.expandBtnSize) - let fillNode = new Circle().size(this.expandBtnSize) - node.x(0).y(-this.expandBtnSize / 2) - fillNode.x(0).y(-this.expandBtnSize / 2) - this.style.iconBtn(node, fillNode) - if (this._expandBtn) this._expandBtn.add(fillNode).add(node) - } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-07-12 18:18:13 - * @Desc: 更新展开收缩按钮位置 - */ - updateExpandBtnPos() { - if (!this._expandBtn) { - return - } - this.renderer.layout.renderExpandBtn(this, this._expandBtn) - } - - /** - * @Author: 王林 - * @Date: 2021-04-11 19:47:01 - * @Desc: 展开收缩按钮 - */ - renderExpandBtn() { - if (!this.nodeData.children || this.nodeData.children.length <= 0 || this.isRoot) { - return - } - this._expandBtn = new G() - this.updateExpandBtnNode() - this._expandBtn.on('mouseover', (e) => { - e.stopPropagation() - this._expandBtn.css({ - cursor: 'pointer' - }) + // 子节点 + if (this.children && this.children.length) { + asyncRun( + this.children.map(item => { + return () => { + item.hide() + } }) - this._expandBtn.on('mouseout', (e) => { - e.stopPropagation() - this._expandBtn.css({ - cursor: 'auto' - }) + ) + } + } + + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-11-23 18:39:14 + * @Desc: 显示节点 + */ + show() { + if (!this.group) { + return + } + this.group.show() + this.showGeneralization() + if (this.parent) { + let index = this.parent.children.indexOf(this) + this.parent._lines[index] && this.parent._lines[index].show() + } + // 子节点 + if (this.children && this.children.length) { + asyncRun( + this.children.map(item => { + return () => { + item.show() + } }) - this._expandBtn.on('click', (e) => { - e.stopPropagation() - // 展开收缩 - this.mindMap.execCommand('SET_NODE_EXPAND', this, !this.nodeData.data.expand) - this.mindMap.emit('expand_btn_click', this) - }) - this.group.add(this._expandBtn) - this.updateExpandBtnPos() + ) } + } - /** - * @Author: 王林 - * @Date: 2021-07-11 13:26:00 - * @Desc: 移除展开收缩按钮 - */ - removeExpandBtn() { - if (this._expandBtn) { - this._expandBtn.off(['mouseover', 'mouseout', 'click']) - this._expandBtn.clear() - this._expandBtn.remove() - this._expandBtn = null - } + /** + * @Author: 王林 + * @Date: 2021-04-10 22:01:53 + * @Desc: 连线 + */ + renderLine(deep = false) { + if (this.nodeData.data.expand === false) { + return } + let childrenLen = this.nodeData.children.length + if (childrenLen > this._lines.length) { + // 创建缺少的线 + new Array(childrenLen - this._lines.length).fill(0).forEach(() => { + this._lines.push(this.draw.path()) + }) + } else if (childrenLen < this._lines.length) { + // 删除多余的线 + this._lines.slice(childrenLen).forEach(line => { + line.remove() + }) + this._lines = this._lines.slice(0, childrenLen) + } + // 画线 + this.renderer.layout.renderLine( + this, + this._lines, + (line, node) => { + // 添加样式 + this.styleLine(line, node) + }, + this.style.getStyle('lineStyle', true) + ) + // 子级的连线也需要更新 + if (deep && this.children && this.children.length > 0) { + this.children.forEach(item => { + item.renderLine(deep) + }) + } + } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-11-25 09:51:37 - * @Desc: 检测当前节点是否是某个节点的祖先节点 - */ - isParent(node) { - if (this === node) { - return false - } - let parent = node.parent - while(parent) { - if (this === parent) { - return true - } - parent = parent.parent - } - return false - } + /** + * javascript comment + * @Author: flydreame + * @Date: 2022-09-17 12:41:29 + * @Desc: 设置连线样式 + */ + styleLine(line, node) { + let width = + node.getSelfInhertStyle('lineWidth') || node.getStyle('lineWidth', true) + let color = + node.getSelfInhertStyle('lineColor') || node.getStyle('lineColor', true) + let dasharray = + node.getSelfInhertStyle('lineDasharray') || + node.getStyle('lineDasharray', true) + this.style.line(line, { + width, + color, + dasharray + }) + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-11-25 10:32:34 - * @Desc: 检测当前节点是否是某个节点的兄弟节点 - */ - isBrother(node) { - if (!this.parent || this === node) { - return false - } - return this.parent.children.find((item) => { - return item === node - }) - } + /** + * @Author: 王林 + * @Date: 2021-07-10 16:40:21 + * @Desc: 移除连线 + */ + removeLine() { + this._lines.forEach(line => { + line.remove() + }) + this._lines = [] + } - /** - * @Author: 王林 - * @Date: 2021-06-20 22:51:57 - * @Desc: 获取padding值 - */ - getPaddingVale() { - return { - paddingX: this.getStyle('paddingX', true, this.nodeData.data.isActive), - paddingY: this.getStyle('paddingY', true, this.nodeData.data.isActive) - } - } + /** + * javascript comment + * @Author: 王林25 + * @Date: 2022-08-01 09:27:30 + * @Desc: 检查是否存在概要 + */ + checkHasGeneralization() { + return !!this.nodeData.data.generalization + } - /** - * @Author: 王林 - * @Date: 2021-05-04 21:48:49 - * @Desc: 获取某个样式 - */ - getStyle(prop, root, isActive) { - let v = this.style.merge(prop, root, isActive) - return v === undefined ? '' : v + /** + * @Author: 王林 + * @Date: 2022-07-31 09:41:28 + * @Desc: 创建概要节点 + */ + createGeneralizationNode() { + if (this.isGeneralization || !this.checkHasGeneralization()) { + return } + if (!this._generalizationLine) { + this._generalizationLine = this.draw.path() + } + if (!this._generalizationNode) { + this._generalizationNode = new Node({ + data: { + data: this.nodeData.data.generalization + }, + uid: this.mindMap.uid++, + renderer: this.renderer, + mindMap: this.mindMap, + draw: this.draw, + isGeneralization: true + }) + this._generalizationNodeWidth = this._generalizationNode.width + this._generalizationNodeHeight = this._generalizationNode.height + this._generalizationNode.generalizationBelongNode = this + if (this.nodeData.data.generalization.isActive) { + this.renderer.addActiveNode(this._generalizationNode) + } + } + } - /** - * javascript comment - * @Author: flydreame - * @Date: 2022-09-17 11:21:15 - * @Desc: 获取自定义样式 - */ - getSelfStyle(prop) { - return this.style.getSelfStyle(prop) - } + /** + * javascript comment + * @Author: 王林25 + * @Date: 2022-08-01 15:38:52 + * @Desc: 更新概要节点 + */ + updateGeneralization() { + this.removeGeneralization() + this.createGeneralizationNode() + } - /** - * javascript comment - * @Author: flydreame - * @Date: 2022-09-17 11:21:26 - * @Desc: 获取最近一个存在自身自定义样式的祖先节点的自定义样式 - */ - getParentSelfStyle(prop) { - if (this.parent) { - return this.parent.getSelfStyle(prop) || this.parent.getParentSelfStyle(prop) - } - return null + /** + * @Author: 王林 + * @Date: 2022-07-30 08:35:51 + * @Desc: 渲染概要节点 + */ + renderGeneralization() { + if (this.isGeneralization) { + return } + if (!this.checkHasGeneralization()) { + this.removeGeneralization() + this._generalizationNodeWidth = 0 + this._generalizationNodeHeight = 0 + return + } + if (this.nodeData.data.expand === false) { + this.removeGeneralization() + return + } + this.createGeneralizationNode() + this.renderer.layout.renderGeneralization( + this, + this._generalizationLine, + this._generalizationNode + ) + this.style.generalizationLine(this._generalizationLine) + this._generalizationNode.render() + } - /** - * javascript comment - * @Author: flydreame - * @Date: 2022-09-17 12:15:30 - * @Desc: 获取自身可继承的自定义样式 - */ - getSelfInhertStyle(prop) { - return this.getSelfStyle(prop) // 自身 - || this.getParentSelfStyle(prop) // 父级 + /** + * @Author: 王林 + * @Date: 2022-07-30 13:11:27 + * @Desc: 删除概要节点 + */ + removeGeneralization() { + if (this._generalizationLine) { + this._generalizationLine.remove() + this._generalizationLine = null } + if (this._generalizationNode) { + // 删除概要节点时要同步从激活节点里删除 + this.renderer.removeActiveNode(this._generalizationNode) + this._generalizationNode.remove() + this._generalizationNode = null + } + // hack修复当激活一个节点时创建概要,然后立即激活创建的概要节点后会重复创建概要节点并且无法删除的问题 + if (this.generalizationBelongNode) { + this.draw + .find('.generalization_' + this.generalizationBelongNode.uid) + .remove() + } + } - /** - * @Author: 王林 - * @Date: 2021-05-04 22:18:07 - * @Desc: 修改某个样式 - */ - setStyle(prop, value, isActive) { - this.mindMap.execCommand('SET_NODE_STYLE', this, prop, value, isActive) + /** + * javascript comment + * @Author: 王林25 + * @Date: 2022-08-01 09:56:46 + * @Desc: 隐藏概要节点 + */ + hideGeneralization() { + if (this._generalizationLine) { + this._generalizationLine.hide() } + if (this._generalizationNode) { + this._generalizationNode.hide() + } + } - /** - * @Author: 王林 - * @Date: 2021-06-22 22:04:02 - * @Desc: 获取数据 - */ - getData(key) { - return key ? this.nodeData.data[key] || '' : this.nodeData.data + /** + * javascript comment + * @Author: 王林25 + * @Date: 2022-08-01 09:57:42 + * @Desc: 显示概要节点 + */ + showGeneralization() { + if (this._generalizationLine) { + this._generalizationLine.show() } + if (this._generalizationNode) { + this._generalizationNode.show() + } + } - /** - * @Author: 王林 - * @Date: 2021-06-22 22:12:01 - * @Desc: 设置数据 - */ - setData(data = {}) { - this.mindMap.execCommand('SET_NODE_DATA', this, data) + /** + * @Author: 王林 + * @Date: 2021-07-10 17:59:14 + * @Desc: 创建或更新展开收缩按钮内容 + */ + updateExpandBtnNode() { + if (this._expandBtn) { + this._expandBtn.clear() } + let iconSvg + if (this.nodeData.data.expand === false) { + iconSvg = btnsSvg.open + } else { + iconSvg = btnsSvg.close + } + let node = SVG(iconSvg).size(this.expandBtnSize, this.expandBtnSize) + let fillNode = new Circle().size(this.expandBtnSize) + node.x(0).y(-this.expandBtnSize / 2) + fillNode.x(0).y(-this.expandBtnSize / 2) + this.style.iconBtn(node, fillNode) + if (this._expandBtn) this._expandBtn.add(fillNode).add(node) + } - /** - * @Author: 王林 - * @Date: 2021-07-10 08:41:28 - * @Desc: 设置文本 - */ - setText(text) { - this.mindMap.execCommand('SET_NODE_TEXT', this, text) + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-07-12 18:18:13 + * @Desc: 更新展开收缩按钮位置 + */ + updateExpandBtnPos() { + if (!this._expandBtn) { + return } + this.renderer.layout.renderExpandBtn(this, this._expandBtn) + } - /** - * @Author: 王林 - * @Date: 2021-07-10 08:42:19 - * @Desc: 设置图片 - */ - setImage(imgData) { - this.mindMap.execCommand('SET_NODE_IMAGE', this, imgData) + /** + * @Author: 王林 + * @Date: 2021-04-11 19:47:01 + * @Desc: 展开收缩按钮 + */ + renderExpandBtn() { + if ( + !this.nodeData.children || + this.nodeData.children.length <= 0 || + this.isRoot + ) { + return } + this._expandBtn = new G() + this.updateExpandBtnNode() + this._expandBtn.on('mouseover', e => { + e.stopPropagation() + this._expandBtn.css({ + cursor: 'pointer' + }) + }) + this._expandBtn.on('mouseout', e => { + e.stopPropagation() + this._expandBtn.css({ + cursor: 'auto' + }) + }) + this._expandBtn.on('click', e => { + e.stopPropagation() + // 展开收缩 + this.mindMap.execCommand( + 'SET_NODE_EXPAND', + this, + !this.nodeData.data.expand + ) + this.mindMap.emit('expand_btn_click', this) + }) + this.group.add(this._expandBtn) + this.updateExpandBtnPos() + } - /** - * @Author: 王林 - * @Date: 2021-07-10 08:47:29 - * @Desc: 设置图标 - */ - setIcon(icons) { - this.mindMap.execCommand('SET_NODE_ICON', this, icons) + /** + * @Author: 王林 + * @Date: 2021-07-11 13:26:00 + * @Desc: 移除展开收缩按钮 + */ + removeExpandBtn() { + if (this._expandBtn) { + this._expandBtn.off(['mouseover', 'mouseout', 'click']) + this._expandBtn.clear() + this._expandBtn.remove() + this._expandBtn = null } + } - /** - * @Author: 王林 - * @Date: 2021-07-10 08:50:41 - * @Desc: 设置超链接 - */ - setHyperlink(link, title) { - this.mindMap.execCommand('SET_NODE_HYPERLINK', this, link, title) + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-11-25 09:51:37 + * @Desc: 检测当前节点是否是某个节点的祖先节点 + */ + isParent(node) { + if (this === node) { + return false } + let parent = node.parent + while (parent) { + if (this === parent) { + return true + } + parent = parent.parent + } + return false + } - /** - * @Author: 王林 - * @Date: 2021-07-10 08:53:24 - * @Desc: 设置备注 - */ - setNote(note) { - this.mindMap.execCommand('SET_NODE_NOTE', this, note) + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-11-25 10:32:34 + * @Desc: 检测当前节点是否是某个节点的兄弟节点 + */ + isBrother(node) { + if (!this.parent || this === node) { + return false } + return this.parent.children.find(item => { + return item === node + }) + } - /** - * @Author: 王林 - * @Date: 2021-07-10 08:55:08 - * @Desc: 设置标签 - */ - setTag(tag) { - this.mindMap.execCommand('SET_NODE_TAG', this, tag) + /** + * @Author: 王林 + * @Date: 2021-06-20 22:51:57 + * @Desc: 获取padding值 + */ + getPaddingVale() { + return { + paddingX: this.getStyle('paddingX', true, this.nodeData.data.isActive), + paddingY: this.getStyle('paddingY', true, this.nodeData.data.isActive) } + } - /** - * javascript comment - * @Author: 王林 - * @Date: 2022-09-12 21:47:45 - * @Desc: 设置形状 - */ - setShape(shape) { - this.mindMap.execCommand('SET_NODE_SHAPE', this, shape) + /** + * @Author: 王林 + * @Date: 2021-05-04 21:48:49 + * @Desc: 获取某个样式 + */ + getStyle(prop, root, isActive) { + let v = this.style.merge(prop, root, isActive) + return v === undefined ? '' : v + } + + /** + * javascript comment + * @Author: flydreame + * @Date: 2022-09-17 11:21:15 + * @Desc: 获取自定义样式 + */ + getSelfStyle(prop) { + return this.style.getSelfStyle(prop) + } + + /** + * javascript comment + * @Author: flydreame + * @Date: 2022-09-17 11:21:26 + * @Desc: 获取最近一个存在自身自定义样式的祖先节点的自定义样式 + */ + getParentSelfStyle(prop) { + if (this.parent) { + return ( + this.parent.getSelfStyle(prop) || this.parent.getParentSelfStyle(prop) + ) } + return null + } + + /** + * javascript comment + * @Author: flydreame + * @Date: 2022-09-17 12:15:30 + * @Desc: 获取自身可继承的自定义样式 + */ + getSelfInhertStyle(prop) { + return ( + this.getSelfStyle(prop) || // 自身 + this.getParentSelfStyle(prop) + ) // 父级 + } + + /** + * @Author: 王林 + * @Date: 2021-05-04 22:18:07 + * @Desc: 修改某个样式 + */ + setStyle(prop, value, isActive) { + this.mindMap.execCommand('SET_NODE_STYLE', this, prop, value, isActive) + } + + /** + * @Author: 王林 + * @Date: 2021-06-22 22:04:02 + * @Desc: 获取数据 + */ + getData(key) { + return key ? this.nodeData.data[key] || '' : this.nodeData.data + } + + /** + * @Author: 王林 + * @Date: 2021-06-22 22:12:01 + * @Desc: 设置数据 + */ + setData(data = {}) { + this.mindMap.execCommand('SET_NODE_DATA', this, data) + } + + /** + * @Author: 王林 + * @Date: 2021-07-10 08:41:28 + * @Desc: 设置文本 + */ + setText(text) { + this.mindMap.execCommand('SET_NODE_TEXT', this, text) + } + + /** + * @Author: 王林 + * @Date: 2021-07-10 08:42:19 + * @Desc: 设置图片 + */ + setImage(imgData) { + this.mindMap.execCommand('SET_NODE_IMAGE', this, imgData) + } + + /** + * @Author: 王林 + * @Date: 2021-07-10 08:47:29 + * @Desc: 设置图标 + */ + setIcon(icons) { + this.mindMap.execCommand('SET_NODE_ICON', this, icons) + } + + /** + * @Author: 王林 + * @Date: 2021-07-10 08:50:41 + * @Desc: 设置超链接 + */ + setHyperlink(link, title) { + this.mindMap.execCommand('SET_NODE_HYPERLINK', this, link, title) + } + + /** + * @Author: 王林 + * @Date: 2021-07-10 08:53:24 + * @Desc: 设置备注 + */ + setNote(note) { + this.mindMap.execCommand('SET_NODE_NOTE', this, note) + } + + /** + * @Author: 王林 + * @Date: 2021-07-10 08:55:08 + * @Desc: 设置标签 + */ + setTag(tag) { + this.mindMap.execCommand('SET_NODE_TAG', this, tag) + } + + /** + * javascript comment + * @Author: 王林 + * @Date: 2022-09-12 21:47:45 + * @Desc: 设置形状 + */ + setShape(shape) { + this.mindMap.execCommand('SET_NODE_SHAPE', this, shape) + } } export default Node diff --git a/simple-mind-map/src/Render.js b/simple-mind-map/src/Render.js index c4a18689..3706809f 100644 --- a/simple-mind-map/src/Render.js +++ b/simple-mind-map/src/Render.js @@ -10,1045 +10,1093 @@ import { lineStyleProps } from './themes/default' // 布局列表 const layouts = { - // 逻辑结构图 - logicalStructure: LogicalStructure, - // 思维导图 - mindMap: MindMap, - // 目录组织图 - catalogOrganization: CatalogOrganization, - // 组织结构图 - organizationStructure: OrganizationStructure + // 逻辑结构图 + logicalStructure: LogicalStructure, + // 思维导图 + mindMap: MindMap, + // 目录组织图 + catalogOrganization: CatalogOrganization, + // 组织结构图 + organizationStructure: OrganizationStructure } -/** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-08 16:25:07 +/** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-08 16:25:07 * @Desc: 渲染 */ class Render { - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-08 16:25:32 - * @Desc: 构造函数 - */ - constructor(opt = {}) { - this.opt = opt - this.mindMap = opt.mindMap - this.themeConfig = this.mindMap.themeConfig - this.draw = this.mindMap.draw - // 渲染树,操作过程中修改的都是这里的数据 - this.renderTree = merge({}, this.mindMap.opt.data || {}) - // 是否重新渲染 - this.reRender = false - // 当前激活的节点列表 - this.activeNodeList = [] - // 根节点 - this.root = null - // 文本编辑框,需要再bindEvent之前实例化,否则单击事件只能触发隐藏文本编辑框,而无法保存文本修改 - this.textEdit = new TextEdit(this) - // 布局 - this.setLayout() - // 绑定事件 - this.bindEvent() - // 注册命令 - this.registerCommands() - // 注册快捷键 - this.registerShortcutKeys() - } + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-08 16:25:32 + * @Desc: 构造函数 + */ + constructor(opt = {}) { + this.opt = opt + this.mindMap = opt.mindMap + this.themeConfig = this.mindMap.themeConfig + this.draw = this.mindMap.draw + // 渲染树,操作过程中修改的都是这里的数据 + this.renderTree = merge({}, this.mindMap.opt.data || {}) + // 是否重新渲染 + this.reRender = false + // 当前激活的节点列表 + this.activeNodeList = [] + // 根节点 + this.root = null + // 文本编辑框,需要再bindEvent之前实例化,否则单击事件只能触发隐藏文本编辑框,而无法保存文本修改 + this.textEdit = new TextEdit(this) + // 布局 + this.setLayout() + // 绑定事件 + this.bindEvent() + // 注册命令 + this.registerCommands() + // 注册快捷键 + this.registerShortcutKeys() + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-07-13 16:20:07 - * @Desc: 设置布局结构 - */ - setLayout() { - this.layout = new (layouts[this.mindMap.opt.layout] ? layouts[this.mindMap.opt.layout] : layouts.logicalStructure)(this) - } + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-07-13 16:20:07 + * @Desc: 设置布局结构 + */ + setLayout() { + this.layout = new ( + layouts[this.mindMap.opt.layout] + ? layouts[this.mindMap.opt.layout] + : layouts.logicalStructure + )(this) + } - /** - * @Author: 王林 - * @Date: 2021-06-20 10:34:06 - * @Desc: 绑定事件 - */ - bindEvent() { - // 点击事件 - this.mindMap.on('draw_click', () => { - // 清除激活状态 - if (this.activeNodeList.length > 0) { - this.mindMap.execCommand('CLEAR_ACTIVE_NODE') - } + /** + * @Author: 王林 + * @Date: 2021-06-20 10:34:06 + * @Desc: 绑定事件 + */ + bindEvent() { + // 点击事件 + this.mindMap.on('draw_click', () => { + // 清除激活状态 + if (this.activeNodeList.length > 0) { + this.mindMap.execCommand('CLEAR_ACTIVE_NODE') + } + }) + } + + /** + * @Author: 王林 + * @Date: 2021-05-04 13:19:06 + * @Desc: 注册命令 + */ + registerCommands() { + // 全选 + this.selectAll = this.selectAll.bind(this) + this.mindMap.command.add('SELECT_ALL', this.selectAll) + // 回退 + this.back = this.back.bind(this) + this.mindMap.command.add('BACK', this.back) + // 前进 + this.forward = this.forward.bind(this) + this.mindMap.command.add('FORWARD', this.forward) + // 插入同级节点 + this.insertNode = this.insertNode.bind(this) + this.mindMap.command.add('INSERT_NODE', this.insertNode) + // 插入子节点 + this.insertChildNode = this.insertChildNode.bind(this) + this.mindMap.command.add('INSERT_CHILD_NODE', this.insertChildNode) + // 上移节点 + this.upNode = this.upNode.bind(this) + this.mindMap.command.add('UP_NODE', this.upNode) + // 下移节点 + this.downNode = this.downNode.bind(this) + this.mindMap.command.add('DOWN_NODE', this.downNode) + // 移动节点 + this.insertAfter = this.insertAfter.bind(this) + this.mindMap.command.add('INSERT_AFTER', this.insertAfter) + this.insertBefore = this.insertBefore.bind(this) + this.mindMap.command.add('INSERT_BEFORE', this.insertBefore) + this.moveNodeTo = this.moveNodeTo.bind(this) + this.mindMap.command.add('MOVE_NODE_TO', this.moveNodeTo) + // 删除节点 + this.removeNode = this.removeNode.bind(this) + this.mindMap.command.add('REMOVE_NODE', this.removeNode) + // 粘贴节点 + this.pasteNode = this.pasteNode.bind(this) + this.mindMap.command.add('PASTE_NODE', this.pasteNode) + // 剪切节点 + this.cutNode = this.cutNode.bind(this) + this.mindMap.command.add('CUT_NODE', this.cutNode) + // 修改节点样式 + this.setNodeStyle = this.setNodeStyle.bind(this) + this.mindMap.command.add('SET_NODE_STYLE', this.setNodeStyle) + // 切换节点是否激活 + this.setNodeActive = this.setNodeActive.bind(this) + this.mindMap.command.add('SET_NODE_ACTIVE', this.setNodeActive) + // 清除所有激活节点 + this.clearAllActive = this.clearAllActive.bind(this) + this.mindMap.command.add('CLEAR_ACTIVE_NODE', this.clearAllActive) + // 切换节点是否展开 + this.setNodeExpand = this.setNodeExpand.bind(this) + this.mindMap.command.add('SET_NODE_EXPAND', this.setNodeExpand) + // 展开所有节点 + this.expandAllNode = this.expandAllNode.bind(this) + this.mindMap.command.add('EXPAND_ALL', this.expandAllNode) + // 收起所有节点 + this.unexpandAllNode = this.unexpandAllNode.bind(this) + this.mindMap.command.add('UNEXPAND_ALL', this.unexpandAllNode) + // 展开到指定层级 + this.expandToLevel = this.expandToLevel.bind(this) + this.mindMap.command.add('UNEXPAND_TO_LEVEL', this.expandToLevel) + // 设置节点数据 + this.setNodeData = this.setNodeData.bind(this) + this.mindMap.command.add('SET_NODE_DATA', this.setNodeData) + // 设置节点文本 + this.setNodeText = this.setNodeText.bind(this) + this.mindMap.command.add('SET_NODE_TEXT', this.setNodeText) + // 设置节点图片 + this.setNodeImage = this.setNodeImage.bind(this) + this.mindMap.command.add('SET_NODE_IMAGE', this.setNodeImage) + // 设置节点图标 + this.setNodeIcon = this.setNodeIcon.bind(this) + this.mindMap.command.add('SET_NODE_ICON', this.setNodeIcon) + // 设置节点超链接 + this.setNodeHyperlink = this.setNodeHyperlink.bind(this) + this.mindMap.command.add('SET_NODE_HYPERLINK', this.setNodeHyperlink) + // 设置节点备注 + this.setNodeNote = this.setNodeNote.bind(this) + this.mindMap.command.add('SET_NODE_NOTE', this.setNodeNote) + // 设置节点标签 + this.setNodeTag = this.setNodeTag.bind(this) + this.mindMap.command.add('SET_NODE_TAG', this.setNodeTag) + // 添加节点概要 + this.addGeneralization = this.addGeneralization.bind(this) + this.mindMap.command.add('ADD_GENERALIZATION', this.addGeneralization) + // 删除节点概要 + this.removeGeneralization = this.removeGeneralization.bind(this) + this.mindMap.command.add('REMOVE_GENERALIZATION', this.removeGeneralization) + // 设置节点自定义位置 + this.setNodeCustomPosition = this.setNodeCustomPosition.bind(this) + this.mindMap.command.add( + 'SET_NODE_CUSTOM_POSITION', + this.setNodeCustomPosition + ) + // 一键整理布局 + this.resetLayout = this.resetLayout.bind(this) + this.mindMap.command.add('RESET_LAYOUT', this.resetLayout) + // 设置节点形状 + this.setNodeShape = this.setNodeShape.bind(this) + this.mindMap.command.add('SET_NODE_SHAPE', this.setNodeShape) + } + + /** + * @Author: 王林 + * @Date: 2021-07-11 16:55:44 + * @Desc: 注册快捷键 + */ + registerShortcutKeys() { + // 插入下级节点 + this.mindMap.keyCommand.addShortcut('Tab', () => { + this.mindMap.execCommand('INSERT_CHILD_NODE') + }) + // 插入同级节点 + this.insertNodeWrap = () => { + if (this.textEdit.showTextEdit) { + return + } + this.mindMap.execCommand('INSERT_NODE') + } + this.mindMap.keyCommand.addShortcut('Enter', this.insertNodeWrap) + // 插入概要 + this.mindMap.keyCommand.addShortcut('Control+s', this.addGeneralization) + // 展开/收起节点 + this.toggleActiveExpand = this.toggleActiveExpand.bind(this) + this.mindMap.keyCommand.addShortcut('/', this.toggleActiveExpand) + // 删除节点 + this.removeNodeWrap = () => { + this.mindMap.execCommand('REMOVE_NODE') + } + this.mindMap.keyCommand.addShortcut('Del|Backspace', this.removeNodeWrap) + // 节点编辑时某些快捷键会存在冲突,需要暂时去除 + this.mindMap.on('before_show_text_edit', () => { + this.startTextEdit() + }) + this.mindMap.on('hide_text_edit', () => { + this.endTextEdit() + }) + // 全选 + this.mindMap.keyCommand.addShortcut('Control+a', () => { + this.mindMap.execCommand('SELECT_ALL') + }) + // 一键整理布局 + this.mindMap.keyCommand.addShortcut('Control+l', this.resetLayout) + // 上移节点 + this.mindMap.keyCommand.addShortcut('Control+Up', this.upNode) + // 下移节点 + this.mindMap.keyCommand.addShortcut('Control+Down', this.downNode) + // 复制节点、剪切节点、粘贴节点的快捷键需开发者自行注册实现,可参考demo + } + + /** + * javascript comment + * @Author: 王林25 + * @Date: 2022-05-09 10:43:52 + * @Desc: 开启文字编辑,会禁用回车键和删除键相关快捷键防止冲突 + */ + startTextEdit() { + this.mindMap.keyCommand.save() + // this.mindMap.keyCommand.removeShortcut('Del|Backspace') + // this.mindMap.keyCommand.removeShortcut('/') + // this.mindMap.keyCommand.removeShortcut('Enter', this.insertNodeWrap) + } + + /** + * javascript comment + * @Author: 王林25 + * @Date: 2022-05-09 10:45:11 + * @Desc: 结束文字编辑,会恢复回车键和删除键相关快捷键 + */ + endTextEdit() { + this.mindMap.keyCommand.restore() + // this.mindMap.keyCommand.addShortcut('Del|Backspace', this.removeNodeWrap) + // this.mindMap.keyCommand.addShortcut('/', this.toggleActiveExpand) + // this.mindMap.keyCommand.addShortcut('Enter', this.insertNodeWrap) + } + + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-08 16:27:55 + * @Desc: 渲染 + */ + render() { + if (this.reRender) { + this.clearActive() + } + this.layout.doLayout(root => { + this.root = root + this.root.render(() => { + this.mindMap.emit('node_tree_render_end') + }) + }) + this.mindMap.emit('node_active', null, this.activeNodeList) + } + + /** + * @Author: 王林 + * @Date: 2021-04-12 22:45:01 + * @Desc: 清除当前激活的节点 + */ + clearActive() { + this.activeNodeList.forEach(item => { + this.setNodeActive(item, false) + }) + this.activeNodeList = [] + } + + /** + * @Author: 王林 + * @Date: 2021-08-03 23:14:34 + * @Desc: 清除当前所有激活节点,并会触发事件 + */ + clearAllActive() { + if (this.activeNodeList.length <= 0) { + return + } + this.clearActive() + this.mindMap.emit('node_active', null, []) + } + + /** + * @Author: 王林 + * @Date: 2021-07-11 10:54:00 + * @Desc: 添加节点到激活列表里 + */ + addActiveNode(node) { + let index = this.findActiveNodeIndex(node) + if (index === -1) { + this.activeNodeList.push(node) + } + } + + /** + * @Author: 王林 + * @Date: 2021-07-10 10:04:04 + * @Desc: 在激活列表里移除某个节点 + */ + removeActiveNode(node) { + let index = this.findActiveNodeIndex(node) + if (index === -1) { + return + } + this.activeNodeList.splice(index, 1) + } + + /** + * @Author: 王林 + * @Date: 2021-07-11 10:55:23 + * @Desc: 检索某个节点在激活列表里的索引 + */ + findActiveNodeIndex(node) { + return this.activeNodeList.findIndex(item => { + return item === node + }) + } + + /** + * @Author: 王林 + * @Date: 2021-05-04 13:46:08 + * @Desc: 获取节点在同级里的索引位置 + */ + getNodeIndex(node) { + return node.parent + ? node.parent.children.findIndex(item => { + return item === node }) - } + : 0 + } - /** - * @Author: 王林 - * @Date: 2021-05-04 13:19:06 - * @Desc: 注册命令 - */ - registerCommands() { - // 全选 - this.selectAll = this.selectAll.bind(this) - this.mindMap.command.add('SELECT_ALL', this.selectAll) - // 回退 - this.back = this.back.bind(this) - this.mindMap.command.add('BACK', this.back) - // 前进 - this.forward = this.forward.bind(this) - this.mindMap.command.add('FORWARD', this.forward) - // 插入同级节点 - this.insertNode = this.insertNode.bind(this) - this.mindMap.command.add('INSERT_NODE', this.insertNode) - // 插入子节点 - this.insertChildNode = this.insertChildNode.bind(this) - this.mindMap.command.add('INSERT_CHILD_NODE', this.insertChildNode) - // 上移节点 - this.upNode = this.upNode.bind(this) - this.mindMap.command.add('UP_NODE', this.upNode) - // 下移节点 - this.downNode = this.downNode.bind(this) - this.mindMap.command.add('DOWN_NODE', this.downNode) - // 移动节点 - this.insertAfter = this.insertAfter.bind(this) - this.mindMap.command.add('INSERT_AFTER', this.insertAfter) - this.insertBefore = this.insertBefore.bind(this) - this.mindMap.command.add('INSERT_BEFORE', this.insertBefore) - this.moveNodeTo = this.moveNodeTo.bind(this) - this.mindMap.command.add('MOVE_NODE_TO', this.moveNodeTo) - // 删除节点 - this.removeNode = this.removeNode.bind(this) - this.mindMap.command.add('REMOVE_NODE', this.removeNode) - // 粘贴节点 - this.pasteNode = this.pasteNode.bind(this) - this.mindMap.command.add('PASTE_NODE', this.pasteNode) - // 剪切节点 - this.cutNode = this.cutNode.bind(this) - this.mindMap.command.add('CUT_NODE', this.cutNode) - // 修改节点样式 - this.setNodeStyle = this.setNodeStyle.bind(this) - this.mindMap.command.add('SET_NODE_STYLE', this.setNodeStyle) - // 切换节点是否激活 - this.setNodeActive = this.setNodeActive.bind(this) - this.mindMap.command.add('SET_NODE_ACTIVE', this.setNodeActive) - // 清除所有激活节点 - this.clearAllActive = this.clearAllActive.bind(this) - this.mindMap.command.add('CLEAR_ACTIVE_NODE', this.clearAllActive) - // 切换节点是否展开 - this.setNodeExpand = this.setNodeExpand.bind(this) - this.mindMap.command.add('SET_NODE_EXPAND', this.setNodeExpand) - // 展开所有节点 - this.expandAllNode = this.expandAllNode.bind(this) - this.mindMap.command.add('EXPAND_ALL', this.expandAllNode) - // 收起所有节点 - this.unexpandAllNode = this.unexpandAllNode.bind(this) - this.mindMap.command.add('UNEXPAND_ALL', this.unexpandAllNode) - // 展开到指定层级 - this.expandToLevel = this.expandToLevel.bind(this) - this.mindMap.command.add('UNEXPAND_TO_LEVEL', this.expandToLevel) - // 设置节点数据 - this.setNodeData = this.setNodeData.bind(this) - this.mindMap.command.add('SET_NODE_DATA', this.setNodeData) - // 设置节点文本 - this.setNodeText = this.setNodeText.bind(this) - this.mindMap.command.add('SET_NODE_TEXT', this.setNodeText) - // 设置节点图片 - this.setNodeImage = this.setNodeImage.bind(this) - this.mindMap.command.add('SET_NODE_IMAGE', this.setNodeImage) - // 设置节点图标 - this.setNodeIcon = this.setNodeIcon.bind(this) - this.mindMap.command.add('SET_NODE_ICON', this.setNodeIcon) - // 设置节点超链接 - this.setNodeHyperlink = this.setNodeHyperlink.bind(this) - this.mindMap.command.add('SET_NODE_HYPERLINK', this.setNodeHyperlink) - // 设置节点备注 - this.setNodeNote = this.setNodeNote.bind(this) - this.mindMap.command.add('SET_NODE_NOTE', this.setNodeNote) - // 设置节点标签 - this.setNodeTag = this.setNodeTag.bind(this) - this.mindMap.command.add('SET_NODE_TAG', this.setNodeTag) - // 添加节点概要 - this.addGeneralization = this.addGeneralization.bind(this) - this.mindMap.command.add('ADD_GENERALIZATION', this.addGeneralization) - // 删除节点概要 - this.removeGeneralization = this.removeGeneralization.bind(this) - this.mindMap.command.add('REMOVE_GENERALIZATION', this.removeGeneralization) - // 设置节点自定义位置 - this.setNodeCustomPosition = this.setNodeCustomPosition.bind(this) - this.mindMap.command.add('SET_NODE_CUSTOM_POSITION', this.setNodeCustomPosition) - // 一键整理布局 - this.resetLayout = this.resetLayout.bind(this) - this.mindMap.command.add('RESET_LAYOUT', this.resetLayout) - // 设置节点形状 - this.setNodeShape = this.setNodeShape.bind(this) - this.mindMap.command.add('SET_NODE_SHAPE', this.setNodeShape) - } + /** + * @Author: 王林 + * @Date: 2021-08-04 23:54:52 + * @Desc: 全选 + */ + selectAll() { + walk( + this.root, + null, + node => { + if (!node.nodeData.data.isActive) { + node.nodeData.data.isActive = true + this.addActiveNode(node) + setTimeout(() => { + node.renderNode() + }, 0) + } + }, + null, + true, + 0, + 0 + ) + } - /** - * @Author: 王林 - * @Date: 2021-07-11 16:55:44 - * @Desc: 注册快捷键 - */ - registerShortcutKeys() { - // 插入下级节点 - this.mindMap.keyCommand.addShortcut('Tab', () => { - this.mindMap.execCommand('INSERT_CHILD_NODE') + /** + * @Author: 王林 + * @Date: 2021-07-11 22:34:12 + * @Desc: 回退 + */ + back(step) { + this.clearAllActive() + let data = this.mindMap.command.back(step) + if (data) { + this.renderTree = data + this.mindMap.reRender() + } + } + + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-07-12 10:44:51 + * @Desc: 前进 + */ + forward(step) { + this.clearAllActive() + let data = this.mindMap.command.forward(step) + if (data) { + this.renderTree = data + this.mindMap.reRender() + } + } + + /** + * @Author: 王林 + * @Date: 2021-05-04 13:19:54 + * @Desc: 插入同级节点,多个节点只会操作第一个节点 + */ + insertNode() { + if (this.activeNodeList.length <= 0) { + return + } + let first = this.activeNodeList[0] + if (first.isRoot) { + this.insertChildNode() + } else { + let text = first.layerIndex === 1 ? '二级节点' : '分支主题' + if (first.layerIndex === 1) { + first.parent.initRender = true + } + let index = this.getNodeIndex(first) + first.parent.nodeData.children.splice(index + 1, 0, { + inserting: true, + data: { + text: text, + expand: true + }, + children: [] + }) + this.mindMap.render() + } + } + + /** + * @Author: 王林 + * @Date: 2021-05-04 13:31:02 + * @Desc: 插入子节点 + */ + insertChildNode() { + if (this.activeNodeList.length <= 0) { + return + } + this.activeNodeList.forEach(node => { + if (!node.nodeData.children) { + node.nodeData.children = [] + } + let text = node.isRoot ? '二级节点' : '分支主题' + node.nodeData.children.push({ + inserting: true, + data: { + text: text, + expand: true + }, + children: [] + }) + // 插入子节点时自动展开子节点 + node.nodeData.data.expand = true + if (node.isRoot) { + node.initRender = true + // this.mindMap.batchExecution.push('renderNode' + index, () => { + // node.renderNode() + // }) + } + }) + this.mindMap.render() + } + + /** + * @Author: 王林 + * @Date: 2021-07-14 23:34:14 + * @Desc: 上移节点,多个节点只会操作第一个节点 + */ + upNode() { + if (this.activeNodeList.length <= 0) { + return + } + let node = this.activeNodeList[0] + if (node.isRoot) { + return + } + let parent = node.parent + let childList = parent.children + let index = childList.findIndex(item => { + return item === node + }) + if (index === -1 || index === 0) { + return + } + let insertIndex = index - 1 + // 节点实例 + childList.splice(index, 1) + childList.splice(insertIndex, 0, node) + // 节点数据 + parent.nodeData.children.splice(index, 1) + parent.nodeData.children.splice(insertIndex, 0, node.nodeData) + this.mindMap.render() + } + + /** + * @Author: 王林 + * @Date: 2021-07-14 23:34:18 + * @Desc: 下移节点,多个节点只会操作第一个节点 + */ + downNode() { + if (this.activeNodeList.length <= 0) { + return + } + let node = this.activeNodeList[0] + if (node.isRoot) { + return + } + let parent = node.parent + let childList = parent.children + let index = childList.findIndex(item => { + return item === node + }) + if (index === -1 || index === childList.length - 1) { + return + } + let insertIndex = index + 1 + // 节点实例 + childList.splice(index, 1) + childList.splice(insertIndex, 0, node) + // 节点数据 + parent.nodeData.children.splice(index, 1) + parent.nodeData.children.splice(insertIndex, 0, node.nodeData) + this.mindMap.render() + } + + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-11-25 10:51:34 + * @Desc: 将节点移动到另一个节点的前面 + */ + insertBefore(node, exist) { + if (node.isRoot) { + return + } + let parent = node.parent + let childList = parent.children + // 要移动节点的索引 + let index = childList.findIndex(item => { + return item === node + }) + if (index === -1) { + return + } + // 目标节点的索引 + let existIndex = childList.findIndex(item => { + return item === exist + }) + if (existIndex === -1) { + return + } + // 当前节点在目标节点前面 + if (index < existIndex) { + existIndex = existIndex - 1 + } + // 节点实例 + childList.splice(index, 1) + childList.splice(existIndex, 0, node) + // 节点数据 + parent.nodeData.children.splice(index, 1) + parent.nodeData.children.splice(existIndex, 0, node.nodeData) + this.mindMap.render() + } + + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-11-25 10:51:34 + * @Desc: 将节点移动到另一个节点的后面 + */ + insertAfter(node, exist) { + if (node.isRoot) { + return + } + let parent = node.parent + let childList = parent.children + // 要移动节点的索引 + let index = childList.findIndex(item => { + return item === node + }) + if (index === -1) { + return + } + // 目标节点的索引 + let existIndex = childList.findIndex(item => { + return item === exist + }) + if (existIndex === -1) { + return + } + // 当前节点在目标节点前面 + if (index < existIndex) { + // do nothing + } else { + existIndex = existIndex + 1 + } + // 节点实例 + childList.splice(index, 1) + childList.splice(existIndex, 0, node) + // 节点数据 + parent.nodeData.children.splice(index, 1) + parent.nodeData.children.splice(existIndex, 0, node.nodeData) + this.mindMap.render() + } + + /** + * @Author: 王林 + * @Date: 2021-05-04 13:40:39 + * @Desc: 移除节点 + */ + removeNode() { + if (this.activeNodeList.length <= 0) { + return + } + for (let i = 0; i < this.activeNodeList.length; i++) { + let node = this.activeNodeList[i] + if (node.isGeneralization) { + // 删除概要节点 + this.setNodeData(node.generalizationBelongNode, { + generalization: null }) - // 插入同级节点 - this.insertNodeWrap = () => { - if (this.textEdit.showTextEdit) { - return - } - this.mindMap.execCommand('INSERT_NODE') - } - this.mindMap.keyCommand.addShortcut('Enter', this.insertNodeWrap) - // 插入概要 - this.mindMap.keyCommand.addShortcut('Control+s', this.addGeneralization) - // 展开/收起节点 - this.toggleActiveExpand = this.toggleActiveExpand.bind(this) - this.mindMap.keyCommand.addShortcut('/', this.toggleActiveExpand) - // 删除节点 - this.removeNodeWrap = () => { - this.mindMap.execCommand('REMOVE_NODE') - } - this.mindMap.keyCommand.addShortcut('Del|Backspace', this.removeNodeWrap) - // 节点编辑时某些快捷键会存在冲突,需要暂时去除 - this.mindMap.on('before_show_text_edit', () => { - this.startTextEdit() + node.generalizationBelongNode.update() + this.removeActiveNode(node) + i-- + } else if (node.isRoot) { + node.children.forEach(child => { + child.remove() }) - this.mindMap.on('hide_text_edit', () => { - this.endTextEdit() - }) - // 全选 - this.mindMap.keyCommand.addShortcut('Control+a', () => { - this.mindMap.execCommand('SELECT_ALL') - }) - // 一键整理布局 - this.mindMap.keyCommand.addShortcut('Control+l', this.resetLayout) - // 上移节点 - this.mindMap.keyCommand.addShortcut('Control+Up', this.upNode) - // 下移节点 - this.mindMap.keyCommand.addShortcut('Control+Down', this.downNode) - // 复制节点、剪切节点、粘贴节点的快捷键需开发者自行注册实现,可参考demo - } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2022-05-09 10:43:52 - * @Desc: 开启文字编辑,会禁用回车键和删除键相关快捷键防止冲突 - */ - startTextEdit() { - this.mindMap.keyCommand.save() - // this.mindMap.keyCommand.removeShortcut('Del|Backspace') - // this.mindMap.keyCommand.removeShortcut('/') - // this.mindMap.keyCommand.removeShortcut('Enter', this.insertNodeWrap) - } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2022-05-09 10:45:11 - * @Desc: 结束文字编辑,会恢复回车键和删除键相关快捷键 - */ - endTextEdit() { - this.mindMap.keyCommand.restore() - // this.mindMap.keyCommand.addShortcut('Del|Backspace', this.removeNodeWrap) - // this.mindMap.keyCommand.addShortcut('/', this.toggleActiveExpand) - // this.mindMap.keyCommand.addShortcut('Enter', this.insertNodeWrap) - } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-08 16:27:55 - * @Desc: 渲染 - */ - render() { - if (this.reRender) { - this.clearActive() - } - this.layout.doLayout((root) => { - this.root = root - this.root.render(() => { - this.mindMap.emit('node_tree_render_end') - }) - }) - this.mindMap.emit('node_active', null, this.activeNodeList) - } - - /** - * @Author: 王林 - * @Date: 2021-04-12 22:45:01 - * @Desc: 清除当前激活的节点 - */ - clearActive() { - this.activeNodeList.forEach((item) => { - this.setNodeActive(item, false) - }) - this.activeNodeList = [] - } - - /** - * @Author: 王林 - * @Date: 2021-08-03 23:14:34 - * @Desc: 清除当前所有激活节点,并会触发事件 - */ - clearAllActive() { - if (this.activeNodeList.length <= 0) { - return - } - this.clearActive() - this.mindMap.emit('node_active', null, []) - } - - /** - * @Author: 王林 - * @Date: 2021-07-11 10:54:00 - * @Desc: 添加节点到激活列表里 - */ - addActiveNode(node) { - let index = this.findActiveNodeIndex(node) - if (index === -1) { - this.activeNodeList.push(node) - } - } - - /** - * @Author: 王林 - * @Date: 2021-07-10 10:04:04 - * @Desc: 在激活列表里移除某个节点 - */ - removeActiveNode(node) { - let index = this.findActiveNodeIndex(node) - if (index === -1) { - return - } - this.activeNodeList.splice(index, 1) - } - - /** - * @Author: 王林 - * @Date: 2021-07-11 10:55:23 - * @Desc: 检索某个节点在激活列表里的索引 - */ - findActiveNodeIndex(node) { - return this.activeNodeList.findIndex((item) => { - return item === node - }) - } - - /** - * @Author: 王林 - * @Date: 2021-05-04 13:46:08 - * @Desc: 获取节点在同级里的索引位置 - */ - getNodeIndex(node) { - return node.parent ? node.parent.children.findIndex((item) => { - return item === node - }) : 0 - } - - /** - * @Author: 王林 - * @Date: 2021-08-04 23:54:52 - * @Desc: 全选 - */ - selectAll() { - walk(this.root, null, (node) => { - if (!node.nodeData.data.isActive) { - node.nodeData.data.isActive = true - this.addActiveNode(node) - setTimeout(() => { - node.renderNode() - }, 0); - } - }, null, true, 0, 0) - } - - /** - * @Author: 王林 - * @Date: 2021-07-11 22:34:12 - * @Desc: 回退 - */ - back(step) { - this.clearAllActive() - let data = this.mindMap.command.back(step) - if (data) { - this.renderTree = data - this.mindMap.reRender() - } - } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-07-12 10:44:51 - * @Desc: 前进 - */ - forward(step) { - this.clearAllActive() - let data = this.mindMap.command.forward(step) - if (data) { - this.renderTree = data - this.mindMap.reRender() - } - } - - /** - * @Author: 王林 - * @Date: 2021-05-04 13:19:54 - * @Desc: 插入同级节点,多个节点只会操作第一个节点 - */ - insertNode() { - if (this.activeNodeList.length <= 0) { - return - } - let first = this.activeNodeList[0] - if (first.isRoot) { - this.insertChildNode() - } else { - let text = first.layerIndex === 1 ? '二级节点' : '分支主题' - if (first.layerIndex === 1) { - first.parent.initRender = true - } - let index = this.getNodeIndex(first) - first.parent.nodeData.children.splice(index + 1, 0, { - "inserting": true, - "data": { - "text": text, - "expand": true - }, - "children": [] - }) - this.mindMap.render() - } - } - - /** - * @Author: 王林 - * @Date: 2021-05-04 13:31:02 - * @Desc: 插入子节点 - */ - insertChildNode() { - if (this.activeNodeList.length <= 0) { - return - } - this.activeNodeList.forEach((node, index) => { - if (!node.nodeData.children) { - node.nodeData.children = [] - } - let text = node.isRoot ? '二级节点' : '分支主题' - node.nodeData.children.push({ - "inserting": true, - "data": { - "text": text, - "expand": true - }, - "children": [] - }) - // 插入子节点时自动展开子节点 - node.nodeData.data.expand = true - if (node.isRoot) { - node.initRender = true - // this.mindMap.batchExecution.push('renderNode' + index, () => { - // node.renderNode() - // }) - } - }) - this.mindMap.render() - } - - /** - * @Author: 王林 - * @Date: 2021-07-14 23:34:14 - * @Desc: 上移节点,多个节点只会操作第一个节点 - */ - upNode() { - if (this.activeNodeList.length <= 0) { - return - } - let node = this.activeNodeList[0] - if (node.isRoot) { - return - } - let parent = node.parent - let childList = parent.children - let index = childList.findIndex((item) => { - return item === node - }) - if (index === -1 || index === 0) { - return - } - let insertIndex = index - 1 - // 节点实例 - childList.splice(index, 1) - childList.splice(insertIndex, 0, node) - // 节点数据 - parent.nodeData.children.splice(index, 1) - parent.nodeData.children.splice(insertIndex, 0, node.nodeData) - this.mindMap.render() - } - - /** - * @Author: 王林 - * @Date: 2021-07-14 23:34:18 - * @Desc: 下移节点,多个节点只会操作第一个节点 - */ - downNode() { - if (this.activeNodeList.length <= 0) { - return - } - let node = this.activeNodeList[0] - if (node.isRoot) { - return - } - let parent = node.parent - let childList = parent.children - let index = childList.findIndex((item) => { - return item === node - }) - if (index === -1 || index === childList.length - 1) { - return - } - let insertIndex = index + 1 - // 节点实例 - childList.splice(index, 1) - childList.splice(insertIndex, 0, node) - // 节点数据 - parent.nodeData.children.splice(index, 1) - parent.nodeData.children.splice(insertIndex, 0, node.nodeData) - this.mindMap.render() - } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-11-25 10:51:34 - * @Desc: 将节点移动到另一个节点的前面 - */ - insertBefore(node, exist) { - if (node.isRoot) { - return - } - let parent = node.parent - let childList = parent.children - // 要移动节点的索引 - let index = childList.findIndex((item) => { - return item === node - }) - if (index === -1) { - return - } - // 目标节点的索引 - let existIndex = childList.findIndex((item) => { - return item === exist - }) - if (existIndex === -1) { - return - } - // 当前节点在目标节点前面 - if (index < existIndex) { - existIndex = existIndex - 1 - } else { - existIndex = existIndex - } - // 节点实例 - childList.splice(index, 1) - childList.splice(existIndex, 0, node) - // 节点数据 - parent.nodeData.children.splice(index, 1) - parent.nodeData.children.splice(existIndex, 0, node.nodeData) - this.mindMap.render() - } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-11-25 10:51:34 - * @Desc: 将节点移动到另一个节点的后面 - */ - insertAfter(node, exist) { - if (node.isRoot) { - return - } - let parent = node.parent - let childList = parent.children - // 要移动节点的索引 - let index = childList.findIndex((item) => { - return item === node - }) - if (index === -1) { - return - } - // 目标节点的索引 - let existIndex = childList.findIndex((item) => { - return item === exist - }) - if (existIndex === -1) { - return - } - // 当前节点在目标节点前面 - if (index < existIndex) { - existIndex = existIndex - } else { - existIndex = existIndex + 1 - } - // 节点实例 - childList.splice(index, 1) - childList.splice(existIndex, 0, node) - // 节点数据 - parent.nodeData.children.splice(index, 1) - parent.nodeData.children.splice(existIndex, 0, node.nodeData) - this.mindMap.render() - } - - /** - * @Author: 王林 - * @Date: 2021-05-04 13:40:39 - * @Desc: 移除节点 - */ - removeNode() { - if (this.activeNodeList.length <= 0) { - return - } - for (let i = 0; i < this.activeNodeList.length; i++) { - let node = this.activeNodeList[i] - if (node.isGeneralization) { - // 删除概要节点 - this.setNodeData(node.generalizationBelongNode, { - generalization: null - }) - node.generalizationBelongNode.update() - this.removeActiveNode(node) - i-- - } else if (node.isRoot) { - node.children.forEach((child) => { - child.remove() - }) - node.children = [] - node.nodeData.children = [] - break - } else { - this.removeActiveNode(node) - this.removeOneNode(node) - i-- - } - } - this.mindMap.emit('node_active', null, []) - this.mindMap.render() - } - - /** - * @Author: 王林 - * @Date: 2021-07-15 22:46:27 - * @Desc: 移除某个指定节点 - */ - removeOneNode(node) { - let index = this.getNodeIndex(node) - node.remove() - node.parent.children.splice(index, 1) - node.parent.nodeData.children.splice(index, 1) - } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-07-15 09:53:23 - * @Desc: 复制节点,多个节点只会操作第一个节点 - */ - copyNode() { - if (this.activeNodeList.length <= 0) { - return - } - return copyNodeTree({}, this.activeNodeList[0], true) - } - - /** - * @Author: 王林 - * @Date: 2021-07-15 22:36:45 - * @Desc: 剪切节点,多个节点只会操作第一个节点 - */ - cutNode(callback) { - if (this.activeNodeList.length <= 0) { - return - } - let node = this.activeNodeList[0] - if (node.isRoot) { - return null - } - let copyData = copyNodeTree({}, node, true) + node.children = [] + node.nodeData.children = [] + break + } else { this.removeActiveNode(node) this.removeOneNode(node) - this.mindMap.emit('node_active', null, this.activeNodeList) - this.mindMap.render() - if (callback && typeof callback === 'function') { - callback(copyData) + i-- + } + } + this.mindMap.emit('node_active', null, []) + this.mindMap.render() + } + + /** + * @Author: 王林 + * @Date: 2021-07-15 22:46:27 + * @Desc: 移除某个指定节点 + */ + removeOneNode(node) { + let index = this.getNodeIndex(node) + node.remove() + node.parent.children.splice(index, 1) + node.parent.nodeData.children.splice(index, 1) + } + + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-07-15 09:53:23 + * @Desc: 复制节点,多个节点只会操作第一个节点 + */ + copyNode() { + if (this.activeNodeList.length <= 0) { + return + } + return copyNodeTree({}, this.activeNodeList[0], true) + } + + /** + * @Author: 王林 + * @Date: 2021-07-15 22:36:45 + * @Desc: 剪切节点,多个节点只会操作第一个节点 + */ + cutNode(callback) { + if (this.activeNodeList.length <= 0) { + return + } + let node = this.activeNodeList[0] + if (node.isRoot) { + return null + } + let copyData = copyNodeTree({}, node, true) + this.removeActiveNode(node) + this.removeOneNode(node) + this.mindMap.emit('node_active', null, this.activeNodeList) + this.mindMap.render() + if (callback && typeof callback === 'function') { + callback(copyData) + } + } + + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-11-24 16:54:01 + * @Desc: 移动一个节点作为另一个节点的子节点 + */ + moveNodeTo(node, toNode) { + if (node.isRoot) { + return + } + let copyData = copyNodeTree({}, node) + this.removeActiveNode(node) + this.removeOneNode(node) + this.mindMap.emit('node_active', null, this.activeNodeList) + toNode.nodeData.children.push(copyData) + this.mindMap.render() + } + + /** + * @Author: 王林 + * @Date: 2021-07-15 20:09:39 + * @Desc: 粘贴节点到节点 + */ + pasteNode(data) { + if (this.activeNodeList.length <= 0) { + return + } + this.activeNodeList.forEach(item => { + item.nodeData.children.push(simpleDeepClone(data)) + }) + this.mindMap.render() + } + + /** + * @Author: 王林 + * @Date: 2021-07-08 21:54:30 + * @Desc: 设置节点样式 + */ + setNodeStyle(node, prop, value, isActive) { + let data = {} + if (isActive) { + data = { + activeStyle: { + ...(node.nodeData.data.activeStyle || {}), + [prop]: value } + } + } else { + data = { + [prop]: value + } } + this.setNodeDataRender(node, data) + // 更新了连线的样式 + if (lineStyleProps.includes(prop)) { + ;(node.parent || node).renderLine(true) + } + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-11-24 16:54:01 - * @Desc: 移动一个节点作为另一个节点的子节点 - */ - moveNodeTo(node, toNode) { - if (node.isRoot) { - return + /** + * @Author: 王林 + * @Date: 2021-07-08 22:13:03 + * @Desc: 设置节点是否激活 + */ + setNodeActive(node, active) { + this.setNodeData(node, { + isActive: active + }) + node.renderNode() + } + + /** + * @Author: 王林 + * @Date: 2021-07-10 16:52:41 + * @Desc: 设置节点是否展开 + */ + setNodeExpand(node, expand) { + this.setNodeData(node, { + expand + }) + if (expand) { + // 展开 + node.children.forEach(item => { + item.render() + }) + node.renderLine() + node.updateExpandBtnNode() + } else { + // 收缩 + node.children.forEach(item => { + item.remove() + }) + node.removeLine() + node.updateExpandBtnNode() + } + this.mindMap.render() + } + + /** + * @Author: 王林 + * @Date: 2021-07-15 23:23:37 + * @Desc: 展开所有 + */ + expandAllNode() { + walk( + this.renderTree, + null, + node => { + if (!node.data.expand) { + node.data.expand = true } - let copyData = copyNodeTree({}, node) - this.removeActiveNode(node) - this.removeOneNode(node) - this.mindMap.emit('node_active', null, this.activeNodeList) - toNode.nodeData.children.push(copyData) - this.mindMap.render() - } + }, + null, + true, + 0, + 0 + ) + this.mindMap.reRender() + } - /** - * @Author: 王林 - * @Date: 2021-07-15 20:09:39 - * @Desc: 粘贴节点到节点 - */ - pasteNode(data) { - if (this.activeNodeList.length <= 0) { - return + /** + * @Author: 王林 + * @Date: 2021-07-15 23:27:14 + * @Desc: 收起所有 + */ + unexpandAllNode() { + walk( + this.renderTree, + null, + (node, parent, isRoot) => { + node._node = null + if (!isRoot) { + node.data.expand = false } - this.activeNodeList.forEach((item) => { - item.nodeData.children.push(simpleDeepClone(data)) - }) - this.mindMap.render() - } + }, + null, + true, + 0, + 0 + ) + this.mindMap.reRender() + } - /** - * @Author: 王林 - * @Date: 2021-07-08 21:54:30 - * @Desc: 设置节点样式 - */ - setNodeStyle(node, prop, value, isActive) { - let data = {} - if (isActive) { - data = { - activeStyle: { - ...(node.nodeData.data.activeStyle || {}), - [prop]: value - } - } - } else { - data = { - [prop]: value - } - } - this.setNodeDataRender(node, data) - // 更新了连线的样式 - if (lineStyleProps.includes(prop)) { - (node.parent || node).renderLine(true) - } - } + /** + * javascript comment + * @Author: 王林25 + * @Date: 2022-09-23 16:31:27 + * @Desc: 展开到指定层级 + */ + expandToLevel(level) { + walk( + this.renderTree, + null, + (node, parent, isRoot, layerIndex) => { + node._node = null + node.data.expand = layerIndex < level + }, + null, + true, + 0, + 0 + ) + this.mindMap.reRender() + } - /** - * @Author: 王林 - * @Date: 2021-07-08 22:13:03 - * @Desc: 设置节点是否激活 - */ - setNodeActive(node, active) { - this.setNodeData(node, { - isActive: active - }) - node.renderNode() - } + /** + * @Author: 王林 + * @Date: 2022-08-14 09:18:40 + * @Desc: 切换激活节点的展开状态 + */ + toggleActiveExpand() { + this.activeNodeList.forEach(node => { + if (node.nodeData.children.length <= 0) { + return + } + this.toggleNodeExpand(node) + }) + } - /** - * @Author: 王林 - * @Date: 2021-07-10 16:52:41 - * @Desc: 设置节点是否展开 - */ - setNodeExpand(node, expand) { - this.setNodeData(node, { - expand - }) - if (expand) { // 展开 - node.children.forEach((item) => { - item.render() - }) - node.renderLine() - node.updateExpandBtnNode() - } else { // 收缩 - node.children.forEach((item) => { - item.remove() - }) - node.removeLine() - node.updateExpandBtnNode() - } - this.mindMap.render() - } + /** + * @Author: 王林 + * @Date: 2021-07-11 17:15:33 + * @Desc: 切换节点展开状态 + */ + toggleNodeExpand(node) { + this.mindMap.execCommand( + 'SET_NODE_EXPAND', + node, + !node.nodeData.data.expand + ) + } - /** - * @Author: 王林 - * @Date: 2021-07-15 23:23:37 - * @Desc: 展开所有 - */ - expandAllNode() { - walk(this.renderTree, null, (node) => { - if (!node.data.expand) { - node.data.expand = true - } - }, null, true, 0, 0) - this.mindMap.reRender() - } + /** + * @Author: 王林 + * @Date: 2021-07-09 22:04:19 + * @Desc: 设置节点文本 + */ + setNodeText(node, text) { + this.setNodeDataRender(node, { + text + }) + } - /** - * @Author: 王林 - * @Date: 2021-07-15 23:27:14 - * @Desc: 收起所有 - */ - unexpandAllNode() { - walk(this.renderTree, null, (node, parent, isRoot) => { - node._node = null - if (!isRoot) { - node.data.expand = false - } - }, null, true, 0, 0) - this.mindMap.reRender() - } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2022-09-23 16:31:27 - * @Desc: 展开到指定层级 - */ - expandToLevel(level) { - walk(this.renderTree, null, (node, parent, isRoot, layerIndex) => { - node._node = null - node.data.expand = layerIndex < level - }, null, true, 0, 0) - this.mindMap.reRender() - } - - /** - * @Author: 王林 - * @Date: 2022-08-14 09:18:40 - * @Desc: 切换激活节点的展开状态 - */ - toggleActiveExpand() { - this.activeNodeList.forEach((node) => { - if (node.nodeData.children.length <= 0) { - return - } - this.toggleNodeExpand(node) - }) - } - - /** - * @Author: 王林 - * @Date: 2021-07-11 17:15:33 - * @Desc: 切换节点展开状态 - */ - toggleNodeExpand(node) { - this.mindMap.execCommand('SET_NODE_EXPAND', node, !node.nodeData.data.expand) - } - - /** - * @Author: 王林 - * @Date: 2021-07-09 22:04:19 - * @Desc: 设置节点文本 - */ - setNodeText(node, text) { - this.setNodeDataRender(node, { - text - }) - } - - /** - * @Author: 王林 - * @Date: 2021-07-10 08:37:40 - * @Desc: 设置节点图片 - */ - setNodeImage(node, { - url, - title, + /** + * @Author: 王林 + * @Date: 2021-07-10 08:37:40 + * @Desc: 设置节点图片 + */ + setNodeImage(node, { url, title, width, height }) { + this.setNodeDataRender(node, { + image: url, + imageTitle: title || '', + imageSize: { width, height - }) { - this.setNodeDataRender(node, { - image: url, - imageTitle: title || '', - imageSize: { - width, - height, - }, - }) - } + } + }) + } - /** - * @Author: 王林 - * @Date: 2021-07-10 08:44:06 - * @Desc: 设置节点图标 - */ - setNodeIcon(node, icons) { - this.setNodeDataRender(node, { - icon: icons - }) - } + /** + * @Author: 王林 + * @Date: 2021-07-10 08:44:06 + * @Desc: 设置节点图标 + */ + setNodeIcon(node, icons) { + this.setNodeDataRender(node, { + icon: icons + }) + } - /** - * @Author: 王林 - * @Date: 2021-07-10 08:49:33 - * @Desc: 设置节点超链接 - */ - setNodeHyperlink(node, link, title = '') { - this.setNodeDataRender(node, { - hyperlink: link, - hyperlinkTitle: title, - }) - } + /** + * @Author: 王林 + * @Date: 2021-07-10 08:49:33 + * @Desc: 设置节点超链接 + */ + setNodeHyperlink(node, link, title = '') { + this.setNodeDataRender(node, { + hyperlink: link, + hyperlinkTitle: title + }) + } - /** - * @Author: 王林 - * @Date: 2021-07-10 08:52:59 - * @Desc: 设置节点备注 - */ - setNodeNote(node, note) { - this.setNodeDataRender(node, { - note - }) - } + /** + * @Author: 王林 + * @Date: 2021-07-10 08:52:59 + * @Desc: 设置节点备注 + */ + setNodeNote(node, note) { + this.setNodeDataRender(node, { + note + }) + } - /** - * @Author: 王林 - * @Date: 2021-07-10 08:54:53 - * @Desc: 设置节点标签 - */ - setNodeTag(node, tag) { - this.setNodeDataRender(node, { - tag - }) - } + /** + * @Author: 王林 + * @Date: 2021-07-10 08:54:53 + * @Desc: 设置节点标签 + */ + setNodeTag(node, tag) { + this.setNodeDataRender(node, { + tag + }) + } - /** - * @Author: 王林 - * @Date: 2022-07-30 20:52:42 - * @Desc: 添加节点概要 - */ - addGeneralization(data) { - if (this.activeNodeList.length <= 0) { - return + /** + * @Author: 王林 + * @Date: 2022-07-30 20:52:42 + * @Desc: 添加节点概要 + */ + addGeneralization(data) { + if (this.activeNodeList.length <= 0) { + return + } + this.activeNodeList.forEach(node => { + if (node.nodeData.data.generalization || node.isRoot) { + return + } + this.setNodeData(node, { + generalization: data || { + text: '概要' } - this.activeNodeList.forEach((node) => { - if (node.nodeData.data.generalization || node.isRoot) { - return - } - this.setNodeData(node, { - generalization: data || { - text: '概要' - } - }) - node.update() + }) + node.update() + }) + this.mindMap.render() + } + + /** + * @Author: 王林 + * @Date: 2022-07-30 21:16:33 + * @Desc: 删除节点概要 + */ + removeGeneralization() { + if (this.activeNodeList.length <= 0) { + return + } + this.activeNodeList.forEach(node => { + if (!node.nodeData.data.generalization) { + return + } + this.setNodeData(node, { + generalization: null + }) + node.update() + }) + this.mindMap.render() + } + + /** + * javascript comment + * @Author: 王林25 + * @Date: 2022-08-02 19:04:24 + * @Desc: 设置节点自定义位置 + */ + setNodeCustomPosition(node, left = undefined, top = undefined) { + let nodeList = [node] || this.activeNodeList + nodeList.forEach(item => { + this.setNodeData(item, { + customLeft: left, + customTop: top + }) + }) + } + + /** + * javascript comment + * @Author: 王林25 + * @Date: 2022-08-02 20:02:50 + * @Desc: 一键整理布局,即去除自定义位置 + */ + resetLayout() { + walk( + this.root, + null, + node => { + node.customLeft = undefined + node.customTop = undefined + this.setNodeData(node, { + customLeft: undefined, + customTop: undefined }) this.mindMap.render() - } + }, + null, + true, + 0, + 0 + ) + } - /** - * @Author: 王林 - * @Date: 2022-07-30 21:16:33 - * @Desc: 删除节点概要 - */ - removeGeneralization() { - if (this.activeNodeList.length <= 0) { - return - } - this.activeNodeList.forEach((node) => { - if (!node.nodeData.data.generalization) { - return - } - this.setNodeData(node, { - generalization: null - }) - node.update() - }) - this.mindMap.render() + /** + * javascript comment + * @Author: 王林 + * @Date: 2022-09-12 21:44:01 + * @Desc: 设置节点形状 + */ + setNodeShape(node, shape) { + if (!shape || !shapeList.includes(shape)) { + return } + let nodeList = [node] || this.activeNodeList + nodeList.forEach(item => { + this.setNodeStyle(item, 'shape', shape) + }) + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2022-08-02 19:04:24 - * @Desc: 设置节点自定义位置 - */ - setNodeCustomPosition(node, left = undefined, top = undefined) { - let nodeList = [node] || this.activeNodeList - nodeList.forEach((item) => { - this.setNodeData(item, { - customLeft: left, - customTop: top - }) - }) - } + /** + * @Author: 王林 + * @Date: 2021-05-04 14:19:48 + * @Desc: 更新节点数据 + */ + setNodeData(node, data) { + Object.keys(data).forEach(key => { + node.nodeData.data[key] = data[key] + }) + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2022-08-02 20:02:50 - * @Desc: 一键整理布局,即去除自定义位置 - */ - resetLayout() { - walk(this.root, null, (node) => { - node.customLeft = undefined - node.customTop = undefined - this.setNodeData(node, { - customLeft: undefined, - customTop: undefined - }) - this.mindMap.render() - }, null, true, 0, 0) - } - - /** - * javascript comment - * @Author: 王林 - * @Date: 2022-09-12 21:44:01 - * @Desc: 设置节点形状 - */ - setNodeShape(node, shape) { - if (!shape || !shapeList.includes(shape)) { - return - } - let nodeList = [node] || this.activeNodeList - nodeList.forEach((item) => { - this.setNodeStyle(item, 'shape', shape) - }) - } - - /** - * @Author: 王林 - * @Date: 2021-05-04 14:19:48 - * @Desc: 更新节点数据 - */ - setNodeData(node, data) { - Object.keys(data).forEach((key) => { - node.nodeData.data[key] = data[key] - }) - } - - /** - * @Author: 王林 - * @Date: 2021-07-10 08:45:48 - * @Desc: 设置节点数据,并判断是否渲染 - */ - setNodeDataRender(node, data) { - this.setNodeData(node, data) - let changed = node.getSize() - node.renderNode() - if (changed) { - if (node.isGeneralization) { - // 概要节点 - node.generalizationBelongNode.updateGeneralization() - } - this.mindMap.render() - } + /** + * @Author: 王林 + * @Date: 2021-07-10 08:45:48 + * @Desc: 设置节点数据,并判断是否渲染 + */ + setNodeDataRender(node, data) { + this.setNodeData(node, data) + let changed = node.getSize() + node.renderNode() + if (changed) { + if (node.isGeneralization) { + // 概要节点 + node.generalizationBelongNode.updateGeneralization() + } + this.mindMap.render() } + } } -export default Render \ No newline at end of file +export default Render diff --git a/simple-mind-map/src/Select.js b/simple-mind-map/src/Select.js index 45f55714..0e4b0c96 100644 --- a/simple-mind-map/src/Select.js +++ b/simple-mind-map/src/Select.js @@ -1,191 +1,198 @@ import { bfsWalk, throttle } from './utils' -/** - * @Author: 王林 - * @Date: 2021-07-10 22:34:51 - * @Desc: 选择节点类 +/** + * @Author: 王林 + * @Date: 2021-07-10 22:34:51 + * @Desc: 选择节点类 */ class Select { - /** - * @Author: 王林 - * @Date: 2021-07-10 22:35:16 - * @Desc: 构造函数 - */ - constructor({ mindMap }) { - this.mindMap = mindMap - this.rect = null - this.isMousedown = false - this.mouseDownX = 0 - this.mouseDownY = 0 - this.mouseMoveX = 0 - this.mouseMoveY = 0 - this.bindEvent() - } + /** + * @Author: 王林 + * @Date: 2021-07-10 22:35:16 + * @Desc: 构造函数 + */ + constructor({ mindMap }) { + this.mindMap = mindMap + this.rect = null + this.isMousedown = false + this.mouseDownX = 0 + this.mouseDownY = 0 + this.mouseMoveX = 0 + this.mouseMoveY = 0 + this.bindEvent() + } - /** - * @Author: 王林 - * @Date: 2021-07-10 22:36:36 - * @Desc: 绑定事件 - */ - bindEvent() { - this.checkInNodes = throttle(this.checkInNodes, 500, this) - this.mindMap.on('mousedown', (e) => { - if (this.mindMap.opt.readonly) { - return - } - if (!e.ctrlKey && e.which !== 3) { - return - } - this.isMousedown = true - let { x, y } = this.mindMap.toPos(e.clientX, e.clientY) - this.mouseDownX = x - this.mouseDownY = y - this.createRect(x, y) + /** + * @Author: 王林 + * @Date: 2021-07-10 22:36:36 + * @Desc: 绑定事件 + */ + bindEvent() { + this.checkInNodes = throttle(this.checkInNodes, 500, this) + this.mindMap.on('mousedown', e => { + if (this.mindMap.opt.readonly) { + return + } + if (!e.ctrlKey && e.which !== 3) { + return + } + this.isMousedown = true + let { x, y } = this.mindMap.toPos(e.clientX, e.clientY) + this.mouseDownX = x + this.mouseDownY = y + this.createRect(x, y) + }) + this.mindMap.on('mousemove', e => { + if (this.mindMap.opt.readonly) { + return + } + if (!this.isMousedown) { + return + } + let { x, y } = this.mindMap.toPos(e.clientX, e.clientY) + this.mouseMoveX = x + this.mouseMoveY = y + if ( + Math.abs(x - this.mouseDownX) <= 10 && + Math.abs(y - this.mouseDownY) <= 10 + ) { + return + } + clearTimeout(this.autoMoveTimer) + this.onMove(x, y) + }) + this.mindMap.on('mouseup', () => { + if (this.mindMap.opt.readonly) { + return + } + if (!this.isMousedown) { + return + } + this.mindMap.emit( + 'node_active', + null, + this.mindMap.renderer.activeNodeList + ) + clearTimeout(this.autoMoveTimer) + this.isMousedown = false + if (this.rect) this.rect.remove() + this.rect = null + }) + } + + /** + * @Author: 王林 + * @Date: 2021-07-13 07:55:49 + * @Desc: 鼠标移动事件 + */ + onMove(x, y) { + // 绘制矩形 + this.rect.plot([ + [this.mouseDownX, this.mouseDownY], + [this.mouseMoveX, this.mouseDownY], + [this.mouseMoveX, this.mouseMoveY], + [this.mouseDownX, this.mouseMoveY] + ]) + this.checkInNodes() + // 检测边缘移动 + let step = this.mindMap.opt.selectTranslateStep + let limit = this.mindMap.opt.selectTranslateLimit + let count = 0 + // 左边缘 + if (x <= this.mindMap.elRect.left + limit) { + this.mouseDownX += step + this.mindMap.view.translateX(step) + count++ + } + // 右边缘 + if (x >= this.mindMap.elRect.right - limit) { + this.mouseDownX -= step + this.mindMap.view.translateX(-step) + count++ + } + // 上边缘 + if (y <= this.mindMap.elRect.top + limit) { + this.mouseDownY += step + this.mindMap.view.translateY(step) + count++ + } + // 下边缘 + if (y >= this.mindMap.elRect.bottom - limit) { + this.mouseDownY -= step + this.mindMap.view.translateY(-step) + count++ + } + if (count > 0) { + this.startAutoMove(x, y) + } + } + + /** + * @Author: 王林 + * @Date: 2021-07-22 08:02:23 + * @Desc: 开启自动移动 + */ + startAutoMove(x, y) { + this.autoMoveTimer = setTimeout(() => { + this.onMove(x, y) + }, 20) + } + + /** + * @Author: 王林 + * @Date: 2021-07-11 10:19:37 + * @Desc: 创建矩形 + */ + createRect(x, y) { + this.rect = this.mindMap.svg + .polygon() + .stroke({ + color: '#0984e3' + }) + .fill({ + color: 'rgba(9,132,227,0.3)' + }) + .plot([[x, y]]) + } + + /** + * @Author: 王林 + * @Date: 2021-07-11 10:20:43 + * @Desc: 检测在选区里的节点 + */ + checkInNodes() { + let { scaleX, scaleY, translateX, translateY } = + this.mindMap.draw.transform() + let minx = Math.min(this.mouseDownX, this.mouseMoveX) + let miny = Math.min(this.mouseDownY, this.mouseMoveY) + let maxx = Math.max(this.mouseDownX, this.mouseMoveX) + let maxy = Math.max(this.mouseDownY, this.mouseMoveY) + bfsWalk(this.mindMap.renderer.root, node => { + let { left, top, width, height } = node + let right = (left + width) * scaleX + translateX + let bottom = (top + height) * scaleY + translateY + left = left * scaleX + translateX + top = top * scaleY + translateY + if (left >= minx && right <= maxx && top >= miny && bottom <= maxy) { + this.mindMap.batchExecution.push('activeNode' + node.uid, () => { + if (node.nodeData.data.isActive) { + return + } + this.mindMap.renderer.setNodeActive(node, true) + this.mindMap.renderer.addActiveNode(node) }) - this.mindMap.on('mousemove', (e) => { - if (this.mindMap.opt.readonly) { - return - } - if (!this.isMousedown) { - return - } - let { x, y } = this.mindMap.toPos(e.clientX, e.clientY) - this.mouseMoveX = x - this.mouseMoveY = y - if (Math.abs(x - this.mouseDownX) <= 10 && Math.abs(y - this.mouseDownY) <= 10) { - return - } - clearTimeout(this.autoMoveTimer) - this.onMove(x, y) + } else if (node.nodeData.data.isActive) { + this.mindMap.batchExecution.push('activeNode' + node.uid, () => { + if (!node.nodeData.data.isActive) { + return + } + this.mindMap.renderer.setNodeActive(node, false) + this.mindMap.renderer.removeActiveNode(node) }) - this.mindMap.on('mouseup', (e) => { - if (this.mindMap.opt.readonly) { - return - } - if (!this.isMousedown) { - return; - } - this.mindMap.emit('node_active', null, this.mindMap.renderer.activeNodeList) - clearTimeout(this.autoMoveTimer) - this.isMousedown = false - if (this.rect) this.rect.remove() - this.rect = null - }) - } - - /** - * @Author: 王林 - * @Date: 2021-07-13 07:55:49 - * @Desc: 鼠标移动事件 - */ - onMove (x, y) { - // 绘制矩形 - this.rect.plot([ - [this.mouseDownX, this.mouseDownY], - [this.mouseMoveX, this.mouseDownY], - [this.mouseMoveX, this.mouseMoveY], - [this.mouseDownX, this.mouseMoveY] - ]) - this.checkInNodes() - // 检测边缘移动 - let step = this.mindMap.opt.selectTranslateStep - let limit = this.mindMap.opt.selectTranslateLimit - let count = 0 - // 左边缘 - if (x <= this.mindMap.elRect.left + limit) { - this.mouseDownX += step - this.mindMap.view.translateX(step) - count++ - } - // 右边缘 - if (x >= this.mindMap.elRect.right - limit) { - this.mouseDownX -= step - this.mindMap.view.translateX(-step) - count++ - } - // 上边缘 - if (y <= this.mindMap.elRect.top + limit) { - this.mouseDownY += step - this.mindMap.view.translateY(step) - count++ - } - // 下边缘 - if (y >= this.mindMap.elRect.bottom - limit) { - this.mouseDownY -= step - this.mindMap.view.translateY(-step) - count++ - } - if (count > 0) { - this.startAutoMove(x, y) - } - } - - /** - * @Author: 王林 - * @Date: 2021-07-22 08:02:23 - * @Desc: 开启自动移动 - */ - startAutoMove(x, y) { - this.autoMoveTimer = setTimeout(() => { - this.onMove(x, y) - }, 20); - } - - /** - * @Author: 王林 - * @Date: 2021-07-11 10:19:37 - * @Desc: 创建矩形 - */ - createRect(x, y) { - this.rect = this.mindMap.svg.polygon().stroke({ - color: '#0984e3' - }).fill({ - color: 'rgba(9,132,227,0.3)' - }).plot([[x, y]]) - } - - /** - * @Author: 王林 - * @Date: 2021-07-11 10:20:43 - * @Desc: 检测在选区里的节点 - */ - checkInNodes() { - let { scaleX, scaleY, translateX, translateY } = this.mindMap.draw.transform() - let minx = Math.min(this.mouseDownX, this.mouseMoveX) - let miny = Math.min(this.mouseDownY, this.mouseMoveY) - let maxx = Math.max(this.mouseDownX, this.mouseMoveX) - let maxy = Math.max(this.mouseDownY, this.mouseMoveY) - bfsWalk(this.mindMap.renderer.root, (node) => { - let { left, top, width, height } = node - let right = (left + width) * scaleX + translateX - let bottom = (top + height) * scaleY + translateY - left = left * scaleX + translateX - top = top * scaleY + translateY - if ( - left >= minx && - right <= maxx && - top >= miny && - bottom <= maxy - ) { - this.mindMap.batchExecution.push('activeNode' + node.uid, () => { - if (node.nodeData.data.isActive) { - return ; - } - this.mindMap.renderer.setNodeActive(node, true) - this.mindMap.renderer.addActiveNode(node) - }) - } else if (node.nodeData.data.isActive) { - this.mindMap.batchExecution.push('activeNode' + node.uid, () => { - if (!node.nodeData.data.isActive) { - return ; - } - this.mindMap.renderer.setNodeActive(node, false) - this.mindMap.renderer.removeActiveNode(node) - }) - } - }) - } + } + }) + } } -export default Select \ No newline at end of file +export default Select diff --git a/simple-mind-map/src/Shape.js b/simple-mind-map/src/Shape.js index be73db8b..df846132 100644 --- a/simple-mind-map/src/Shape.js +++ b/simple-mind-map/src/Shape.js @@ -1,178 +1,178 @@ -/** - * @Author: 王林 - * @Date: 2022-08-22 21:32:50 - * @Desc: 节点形状类 +/** + * @Author: 王林 + * @Date: 2022-08-22 21:32:50 + * @Desc: 节点形状类 */ - export default class Shape { - constructor(node) { - this.node = node - } +export default class Shape { + constructor(node) { + this.node = node + } - /** - * @Author: 王林 - * @Date: 2022-08-17 22:32:32 - * @Desc: 形状需要的padding - */ - getShapePadding(width, height, paddingX, paddingY) { - const shape = this.node.getShape() - const defaultPaddingX = 15 - const defaultPaddingY = 5 - const actWidth = width + paddingX * 2 - const actHeight = height + paddingY * 2 - const actOffset = Math.abs(actWidth - actHeight) - switch (shape) { - case 'roundedRectangle': - return { - paddingX: height > width ? (height - width) / 2 : 0, - paddingY: 0 - } - case 'diamond': - return { - paddingX: width / 2, - paddingY: height / 2 - } - case 'parallelogram': - return { - paddingX: paddingX <= 0 ? defaultPaddingX : 0, - paddingY: 0 - } - case 'outerTriangularRectangle': - return { - paddingX: paddingX <= 0 ? defaultPaddingX : 0, - paddingY: 0 - } - case 'innerTriangularRectangle': - return { - paddingX: paddingX <= 0 ? defaultPaddingX : 0, - paddingY: 0 - } - case 'ellipse': - return { - paddingX: paddingX <= 0 ? defaultPaddingX : 0, - paddingY: paddingY <= 0 ? defaultPaddingY : 0 - } - case 'circle': - return { - paddingX: actHeight > actWidth ? actOffset / 2 : 0, - paddingY: actHeight < actWidth ? actOffset / 2 : 0, - } - default: - return { - paddingX: 0, - paddingY: 0 - } + /** + * @Author: 王林 + * @Date: 2022-08-17 22:32:32 + * @Desc: 形状需要的padding + */ + getShapePadding(width, height, paddingX, paddingY) { + const shape = this.node.getShape() + const defaultPaddingX = 15 + const defaultPaddingY = 5 + const actWidth = width + paddingX * 2 + const actHeight = height + paddingY * 2 + const actOffset = Math.abs(actWidth - actHeight) + switch (shape) { + case 'roundedRectangle': + return { + paddingX: height > width ? (height - width) / 2 : 0, + paddingY: 0 + } + case 'diamond': + return { + paddingX: width / 2, + paddingY: height / 2 + } + case 'parallelogram': + return { + paddingX: paddingX <= 0 ? defaultPaddingX : 0, + paddingY: 0 + } + case 'outerTriangularRectangle': + return { + paddingX: paddingX <= 0 ? defaultPaddingX : 0, + paddingY: 0 + } + case 'innerTriangularRectangle': + return { + paddingX: paddingX <= 0 ? defaultPaddingX : 0, + paddingY: 0 + } + case 'ellipse': + return { + paddingX: paddingX <= 0 ? defaultPaddingX : 0, + paddingY: paddingY <= 0 ? defaultPaddingY : 0 + } + case 'circle': + return { + paddingX: actHeight > actWidth ? actOffset / 2 : 0, + paddingY: actHeight < actWidth ? actOffset / 2 : 0 + } + default: + return { + paddingX: 0, + paddingY: 0 } } + } - /** - * @Author: 王林 - * @Date: 2022-08-17 22:22:53 - * @Desc: 创建形状节点 - */ - createShape() { - const shape = this.node.getShape() - let { width, height } = this.node - let node = null - // 矩形 - if (shape === 'rectangle') { - node = this.node.group.rect(width, height) - } else if (shape === 'diamond') { - // 菱形 - node = this.createDiamond() - } else if (shape === 'parallelogram') { - // 平行四边形 - node = this.createParallelogram() - } else if (shape === 'roundedRectangle') { - // 圆角矩形 - node = this.createRoundedRectangle() - } else if (shape === 'octagonalRectangle') { - // 八角矩形 - node = this.createOctagonalRectangle() - } else if (shape === 'outerTriangularRectangle') { - // 外三角矩形 - node = this.createOuterTriangularRectangle() - } else if (shape === 'innerTriangularRectangle') { - // 内三角矩形 - node = this.createInnerTriangularRectangle() - } else if (shape === 'ellipse') { - // 椭圆 - node = this.createEllipse() - } else if (shape === 'circle') { - // 圆 - node = this.createCircle() - } - return node + /** + * @Author: 王林 + * @Date: 2022-08-17 22:22:53 + * @Desc: 创建形状节点 + */ + createShape() { + const shape = this.node.getShape() + let { width, height } = this.node + let node = null + // 矩形 + if (shape === 'rectangle') { + node = this.node.group.rect(width, height) + } else if (shape === 'diamond') { + // 菱形 + node = this.createDiamond() + } else if (shape === 'parallelogram') { + // 平行四边形 + node = this.createParallelogram() + } else if (shape === 'roundedRectangle') { + // 圆角矩形 + node = this.createRoundedRectangle() + } else if (shape === 'octagonalRectangle') { + // 八角矩形 + node = this.createOctagonalRectangle() + } else if (shape === 'outerTriangularRectangle') { + // 外三角矩形 + node = this.createOuterTriangularRectangle() + } else if (shape === 'innerTriangularRectangle') { + // 内三角矩形 + node = this.createInnerTriangularRectangle() + } else if (shape === 'ellipse') { + // 椭圆 + node = this.createEllipse() + } else if (shape === 'circle') { + // 圆 + node = this.createCircle() } + return node + } - /** - * @Author: 王林 - * @Date: 2022-09-04 09:08:54 - * @Desc: 创建菱形 - */ - createDiamond() { - let { width, height } = this.node - let halfWidth = width / 2 - let halfHeight = height / 2 - let topX = halfWidth - let topY = 0 - let rightX = width - let rightY = halfHeight - let bottomX = halfWidth - let bottomY = height - let leftX = 0 - let leftY = halfHeight - return this.node.group.polygon(` + /** + * @Author: 王林 + * @Date: 2022-09-04 09:08:54 + * @Desc: 创建菱形 + */ + createDiamond() { + let { width, height } = this.node + let halfWidth = width / 2 + let halfHeight = height / 2 + let topX = halfWidth + let topY = 0 + let rightX = width + let rightY = halfHeight + let bottomX = halfWidth + let bottomY = height + let leftX = 0 + let leftY = halfHeight + return this.node.group.polygon(` ${topX}, ${topY} ${rightX}, ${rightY} ${bottomX}, ${bottomY} ${leftX}, ${leftY} `) - } + } - /** - * @Author: 王林 - * @Date: 2022-09-03 16:14:12 - * @Desc: 创建平行四边形 - */ - createParallelogram() { - let { paddingX } = this.node.getPaddingVale() - paddingX = paddingX || this.node.shapePadding.paddingX - let { width, height } = this.node - return this.node.group.polygon(` + /** + * @Author: 王林 + * @Date: 2022-09-03 16:14:12 + * @Desc: 创建平行四边形 + */ + createParallelogram() { + let { paddingX } = this.node.getPaddingVale() + paddingX = paddingX || this.node.shapePadding.paddingX + let { width, height } = this.node + return this.node.group.polygon(` ${paddingX}, ${0} ${width}, ${0} ${width - paddingX}, ${height} ${0}, ${height} `) - } + } - /** - * @Author: 王林 - * @Date: 2022-09-03 16:50:23 - * @Desc: 创建圆角矩形 - */ - createRoundedRectangle() { - let { width, height } = this.node - let halfHeight = height / 2 - return this.node.group.path(` + /** + * @Author: 王林 + * @Date: 2022-09-03 16:50:23 + * @Desc: 创建圆角矩形 + */ + createRoundedRectangle() { + let { width, height } = this.node + let halfHeight = height / 2 + return this.node.group.path(` M${halfHeight},0 L${width - halfHeight},0 A${height / 2},${height / 2} 0 0,1 ${width - halfHeight},${height} L${halfHeight},${height} A${height / 2},${height / 2} 0 0,1 ${halfHeight},${0} `) - } + } - /** - * javascript comment - * @Author: 王林 - * @Date: 2022-09-12 16:14:08 - * @Desc: 创建八角矩形 - */ - createOctagonalRectangle() { - let w = 5 - let { width, height } = this.node - return this.node.group.polygon(` + /** + * javascript comment + * @Author: 王林 + * @Date: 2022-09-12 16:14:08 + * @Desc: 创建八角矩形 + */ + createOctagonalRectangle() { + let w = 5 + let { width, height } = this.node + return this.node.group.polygon(` ${0}, ${w} ${w}, ${0} ${width - w}, ${0} @@ -182,19 +182,19 @@ ${w}, ${height} ${0}, ${height - w} `) - } + } - /** - * javascript comment - * @Author: 王林 - * @Date: 2022-09-12 20:55:50 - * @Desc: 创建外三角矩形 - */ - createOuterTriangularRectangle() { - let { paddingX } = this.node.getPaddingVale() - paddingX = paddingX || this.node.shapePadding.paddingX - let { width, height } = this.node - return this.node.group.polygon(` + /** + * javascript comment + * @Author: 王林 + * @Date: 2022-09-12 20:55:50 + * @Desc: 创建外三角矩形 + */ + createOuterTriangularRectangle() { + let { paddingX } = this.node.getPaddingVale() + paddingX = paddingX || this.node.shapePadding.paddingX + let { width, height } = this.node + return this.node.group.polygon(` ${paddingX}, ${0} ${width - paddingX}, ${0} ${width}, ${height / 2} @@ -202,19 +202,19 @@ ${paddingX}, ${height} ${0}, ${height / 2} `) - } + } - /** - * javascript comment - * @Author: 王林 - * @Date: 2022-09-12 20:59:37 - * @Desc: 创建内三角矩形 - */ - createInnerTriangularRectangle() { - let { paddingX } = this.node.getPaddingVale() - paddingX = paddingX || this.node.shapePadding.paddingX - let { width, height } = this.node - return this.node.group.polygon(` + /** + * javascript comment + * @Author: 王林 + * @Date: 2022-09-12 20:59:37 + * @Desc: 创建内三角矩形 + */ + createInnerTriangularRectangle() { + let { paddingX } = this.node.getPaddingVale() + paddingX = paddingX || this.node.shapePadding.paddingX + let { width, height } = this.node + return this.node.group.polygon(` ${0}, ${0} ${width}, ${0} ${width - paddingX / 2}, ${height / 2} @@ -222,44 +222,54 @@ ${0}, ${height} ${paddingX / 2}, ${height / 2} `) - } + } - /** - * javascript comment - * @Author: 王林 - * @Date: 2022-09-12 21:06:31 - * @Desc: 创建椭圆 - */ - createEllipse() { - let { width, height } = this.node - let halfWidth = width / 2 - let halfHeight = height / 2 - return this.node.group.path(` + /** + * javascript comment + * @Author: 王林 + * @Date: 2022-09-12 21:06:31 + * @Desc: 创建椭圆 + */ + createEllipse() { + let { width, height } = this.node + let halfWidth = width / 2 + let halfHeight = height / 2 + return this.node.group.path(` M${halfWidth},0 A${halfWidth},${halfHeight} 0 0,1 ${halfWidth},${height} M${halfWidth},${height} A${halfWidth},${halfHeight} 0 0,1 ${halfWidth},${0} `) - } + } - /** - * javascript comment - * @Author: 王林 - * @Date: 2022-09-12 21:14:04 - * @Desc: 创建圆 - */ - createCircle() { - let { width, height } = this.node - let halfWidth = width / 2 - let halfHeight = height / 2 - return this.node.group.path(` + /** + * javascript comment + * @Author: 王林 + * @Date: 2022-09-12 21:14:04 + * @Desc: 创建圆 + */ + createCircle() { + let { width, height } = this.node + let halfWidth = width / 2 + let halfHeight = height / 2 + return this.node.group.path(` M${halfWidth},0 A${halfWidth},${halfHeight} 0 0,1 ${halfWidth},${height} M${halfWidth},${height} A${halfWidth},${halfHeight} 0 0,1 ${halfWidth},${0} `) - } + } } // 形状列表 -export const shapeList = ['rectangle', 'diamond', 'parallelogram', 'roundedRectangle', 'octagonalRectangle', 'outerTriangularRectangle', 'innerTriangularRectangle', 'ellipse', 'circle'] \ No newline at end of file +export const shapeList = [ + 'rectangle', + 'diamond', + 'parallelogram', + 'roundedRectangle', + 'octagonalRectangle', + 'outerTriangularRectangle', + 'innerTriangularRectangle', + 'ellipse', + 'circle' +] diff --git a/simple-mind-map/src/Style.js b/simple-mind-map/src/Style.js index 130b0644..9d2dba3b 100644 --- a/simple-mind-map/src/Style.js +++ b/simple-mind-map/src/Style.js @@ -1,210 +1,230 @@ -import { tagColorList } from './utils/constant'; +import { tagColorList } from './utils/constant' const rootProp = ['paddingX', 'paddingY'] -/** - * @Author: 王林 - * @Date: 2021-04-11 10:09:08 - * @Desc: 样式类 +/** + * @Author: 王林 + * @Date: 2021-04-11 10:09:08 + * @Desc: 样式类 */ class Style { - /** - * @Author: 王林 - * @Date: 2021-04-11 16:01:53 - * @Desc: 设置背景样式 - */ - static setBackgroundStyle(el, themeConfig) { - let { backgroundColor, backgroundImage, backgroundRepeat } = themeConfig - el.style.backgroundColor = backgroundColor - if (backgroundImage) { - el.style.backgroundImage = `url(${backgroundImage})` - el.style.backgroundRepeat = backgroundRepeat - } + /** + * @Author: 王林 + * @Date: 2021-04-11 16:01:53 + * @Desc: 设置背景样式 + */ + static setBackgroundStyle(el, themeConfig) { + let { backgroundColor, backgroundImage, backgroundRepeat } = themeConfig + el.style.backgroundColor = backgroundColor + if (backgroundImage) { + el.style.backgroundImage = `url(${backgroundImage})` + el.style.backgroundRepeat = backgroundRepeat } + } - /** - * @Author: 王林 - * @Date: 2021-04-11 10:10:11 - * @Desc: 构造函数 - */ - constructor(ctx, themeConfig) { - this.ctx = ctx - this.themeConfig = themeConfig - } + /** + * @Author: 王林 + * @Date: 2021-04-11 10:10:11 + * @Desc: 构造函数 + */ + constructor(ctx, themeConfig) { + this.ctx = ctx + this.themeConfig = themeConfig + } - /** - * @Author: 王林 - * @Date: 2021-07-12 07:40:14 - * @Desc: 更新主题配置 - */ - updateThemeConfig(themeConfig) { - this.themeConfig = themeConfig - } + /** + * @Author: 王林 + * @Date: 2021-07-12 07:40:14 + * @Desc: 更新主题配置 + */ + updateThemeConfig(themeConfig) { + this.themeConfig = themeConfig + } - /** - * @Author: 王林 - * @Date: 2021-04-11 12:02:55 - * @Desc: 合并样式 - */ - merge(prop, root, isActive) { - // 三级及以下节点 - let defaultConfig = this.themeConfig.node - if (root || rootProp.includes(prop)) {// 直接使用最外层样式 - defaultConfig = this.themeConfig - } else if (this.ctx.isGeneralization) {// 概要节点 - defaultConfig = this.themeConfig.generalization - } else if (this.ctx.layerIndex === 0) {// 根节点 - defaultConfig = this.themeConfig.root - } else if (this.ctx.layerIndex === 1) {// 二级节点 - defaultConfig = this.themeConfig.second - } - // 激活状态 - if (isActive !== undefined ? isActive : this.ctx.nodeData.data.isActive) { - if (this.ctx.nodeData.data.activeStyle && this.ctx.nodeData.data.activeStyle[prop] !== undefined) { - return this.ctx.nodeData.data.activeStyle[prop]; - } else if (defaultConfig.active && defaultConfig.active[prop]) { - return defaultConfig.active[prop] - } - } - // 优先使用节点本身的样式 - return this.getSelfStyle(prop) !== undefined ? this.getSelfStyle(prop) : defaultConfig[prop] + /** + * @Author: 王林 + * @Date: 2021-04-11 12:02:55 + * @Desc: 合并样式 + */ + merge(prop, root, isActive) { + // 三级及以下节点 + let defaultConfig = this.themeConfig.node + if (root || rootProp.includes(prop)) { + // 直接使用最外层样式 + defaultConfig = this.themeConfig + } else if (this.ctx.isGeneralization) { + // 概要节点 + defaultConfig = this.themeConfig.generalization + } else if (this.ctx.layerIndex === 0) { + // 根节点 + defaultConfig = this.themeConfig.root + } else if (this.ctx.layerIndex === 1) { + // 二级节点 + defaultConfig = this.themeConfig.second } + // 激活状态 + if (isActive !== undefined ? isActive : this.ctx.nodeData.data.isActive) { + if ( + this.ctx.nodeData.data.activeStyle && + this.ctx.nodeData.data.activeStyle[prop] !== undefined + ) { + return this.ctx.nodeData.data.activeStyle[prop] + } else if (defaultConfig.active && defaultConfig.active[prop]) { + return defaultConfig.active[prop] + } + } + // 优先使用节点本身的样式 + return this.getSelfStyle(prop) !== undefined + ? this.getSelfStyle(prop) + : defaultConfig[prop] + } - /** - * javascript comment - * @Author: 王林 - * @Date: 2022-09-12 21:55:57 - * @Desc: 获取某个样式值 - */ - getStyle(prop, root, isActive) { - return this.merge(prop, root, isActive) - } + /** + * javascript comment + * @Author: 王林 + * @Date: 2022-09-12 21:55:57 + * @Desc: 获取某个样式值 + */ + getStyle(prop, root, isActive) { + return this.merge(prop, root, isActive) + } - /** - * javascript comment - * @Author: flydreame - * @Date: 2022-09-17 12:09:39 - * @Desc: 获取自身自定义样式 - */ - getSelfStyle(prop) { - return this.ctx.nodeData.data[prop] - } + /** + * javascript comment + * @Author: flydreame + * @Date: 2022-09-17 12:09:39 + * @Desc: 获取自身自定义样式 + */ + getSelfStyle(prop) { + return this.ctx.nodeData.data[prop] + } - /** - * @Author: 王林 - * @Date: 2021-04-11 10:12:56 - * @Desc: 矩形 - */ - rect(node) { - this.shape(node) - node.radius(this.merge('borderRadius')) - } + /** + * @Author: 王林 + * @Date: 2021-04-11 10:12:56 + * @Desc: 矩形 + */ + rect(node) { + this.shape(node) + node.radius(this.merge('borderRadius')) + } - /** - * javascript comment - * @Author: 王林 - * @Date: 2022-09-12 15:04:28 - * @Desc: 矩形外的其他形状 - */ - shape(node) { - node.fill({ - color: this.merge('fillColor') - }).stroke({ - color: this.merge('borderColor'), - width: this.merge('borderWidth'), - dasharray: this.merge('borderDasharray') - }) - } + /** + * javascript comment + * @Author: 王林 + * @Date: 2022-09-12 15:04:28 + * @Desc: 矩形外的其他形状 + */ + shape(node) { + node + .fill({ + color: this.merge('fillColor') + }) + .stroke({ + color: this.merge('borderColor'), + width: this.merge('borderWidth'), + dasharray: this.merge('borderDasharray') + }) + } - /** - * @Author: 王林 - * @Date: 2021-04-11 12:07:59 - * @Desc: 文字 - */ - text(node) { - node.fill({ - color: this.merge('color') - }).css({ - 'font-family': this.merge('fontFamily'), - 'font-size': this.merge('fontSize'), - 'font-weight': this.merge('fontWeight'), - 'font-style': this.merge('fontStyle'), - 'text-decoration': this.merge('textDecoration') - }) - } + /** + * @Author: 王林 + * @Date: 2021-04-11 12:07:59 + * @Desc: 文字 + */ + text(node) { + node + .fill({ + color: this.merge('color') + }) + .css({ + 'font-family': this.merge('fontFamily'), + 'font-size': this.merge('fontSize'), + 'font-weight': this.merge('fontWeight'), + 'font-style': this.merge('fontStyle'), + 'text-decoration': this.merge('textDecoration') + }) + } - /** - * @Author: 王林 - * @Date: 2021-04-13 08:14:34 - * @Desc: html文字节点 - */ - domText(node, fontSizeScale = 1) { - node.style.fontFamily = this.merge('fontFamily') - node.style.fontSize = this.merge('fontSize') * fontSizeScale + 'px' - node.style.fontWeight = this.merge('fontWeight') || 'normal' - } + /** + * @Author: 王林 + * @Date: 2021-04-13 08:14:34 + * @Desc: html文字节点 + */ + domText(node, fontSizeScale = 1) { + node.style.fontFamily = this.merge('fontFamily') + node.style.fontSize = this.merge('fontSize') * fontSizeScale + 'px' + node.style.fontWeight = this.merge('fontWeight') || 'normal' + } - /** - * @Author: 王林 - * @Date: 2021-06-20 20:02:18 - * @Desc: 标签文字 - */ - tagText(node, index) { - node.fill({ - color: tagColorList[index].color - }).css({ - 'font-size': '12px' - }) - } + /** + * @Author: 王林 + * @Date: 2021-06-20 20:02:18 + * @Desc: 标签文字 + */ + tagText(node, index) { + node + .fill({ + color: tagColorList[index].color + }) + .css({ + 'font-size': '12px' + }) + } - /** - * @Author: 王林 - * @Date: 2021-06-20 21:04:11 - * @Desc: 标签矩形 - */ - tagRect(node, index) { - node.fill({ - color: tagColorList[index].background - }) - } + /** + * @Author: 王林 + * @Date: 2021-06-20 21:04:11 + * @Desc: 标签矩形 + */ + tagRect(node, index) { + node.fill({ + color: tagColorList[index].background + }) + } - /** - * @Author: 王林 - * @Date: 2021-07-03 22:37:19 - * @Desc: 内置图标 - */ - iconNode(node) { - node.attr({ - fill: this.merge('color') - }) - } + /** + * @Author: 王林 + * @Date: 2021-07-03 22:37:19 + * @Desc: 内置图标 + */ + iconNode(node) { + node.attr({ + fill: this.merge('color') + }) + } - /** - * @Author: 王林 - * @Date: 2021-04-11 14:50:49 - * @Desc: 连线 - */ - line(node, { width, color, dasharray } = {}) { - node.stroke({ width, color, dasharray }).fill({ color: 'none' }) - } + /** + * @Author: 王林 + * @Date: 2021-04-11 14:50:49 + * @Desc: 连线 + */ + line(node, { width, color, dasharray } = {}) { + node.stroke({ width, color, dasharray }).fill({ color: 'none' }) + } - /** - * @Author: 王林 - * @Date: 2022-07-30 16:19:03 - * @Desc: 概要连线 - */ - generalizationLine(node) { - node.stroke({ width: this.merge('generalizationLineWidth', true), color: this.merge('generalizationLineColor', true) }).fill({ color: 'none' }) - } + /** + * @Author: 王林 + * @Date: 2022-07-30 16:19:03 + * @Desc: 概要连线 + */ + generalizationLine(node) { + node + .stroke({ + width: this.merge('generalizationLineWidth', true), + color: this.merge('generalizationLineColor', true) + }) + .fill({ color: 'none' }) + } - /** - * @Author: 王林 - * @Date: 2021-04-11 20:03:59 - * @Desc: 按钮 - */ - iconBtn(node, fillNode) { - node.fill({ color: '#808080' }) - fillNode.fill({ color: '#fff' }) - } + /** + * @Author: 王林 + * @Date: 2021-04-11 20:03:59 + * @Desc: 按钮 + */ + iconBtn(node, fillNode) { + node.fill({ color: '#808080' }) + fillNode.fill({ color: '#fff' }) + } } -export default Style \ No newline at end of file +export default Style diff --git a/simple-mind-map/src/TextEdit.js b/simple-mind-map/src/TextEdit.js index f80d35af..480acc61 100644 --- a/simple-mind-map/src/TextEdit.js +++ b/simple-mind-map/src/TextEdit.js @@ -1,146 +1,150 @@ -import { - getStrWithBrFromHtml -} from './utils' +import { getStrWithBrFromHtml } from './utils' -/** - * javascript comment - * @Author: 王林25 - * @Date: 2021-06-19 11:11:28 - * @Desc: 节点文字编辑类 +/** + * javascript comment + * @Author: 王林25 + * @Date: 2021-06-19 11:11:28 + * @Desc: 节点文字编辑类 */ export default class TextEdit { - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-06-19 11:22:57 - * @Desc: 构造函数 - */ - constructor(renderer) { - this.renderer = renderer - this.mindMap = renderer.mindMap - // 文本编辑框 - this.textEditNode = null - // 文本编辑框是否显示 - this.showTextEdit = false - this.bindEvent() - } + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-06-19 11:22:57 + * @Desc: 构造函数 + */ + constructor(renderer) { + this.renderer = renderer + this.mindMap = renderer.mindMap + // 文本编辑框 + this.textEditNode = null + // 文本编辑框是否显示 + this.showTextEdit = false + this.bindEvent() + } - /** - * @Author: 王林 - * @Date: 2021-04-24 13:27:04 - * @Desc: 事件 - */ - bindEvent() { - this.show = this.show.bind(this) - // 节点双击事件 - this.mindMap.on('node_dblclick', this.show) - // 点击事件 - this.mindMap.on('draw_click', () => { - // 隐藏文本编辑框 - this.hideEditTextBox() - }) - // 展开收缩按钮点击事件 - this.mindMap.on('expand_btn_click', () => { - this.hideEditTextBox() - }) - // 节点激活前事件 - this.mindMap.on('before_node_active', () => { - this.hideEditTextBox() - }) - // 注册编辑快捷键 - this.mindMap.keyCommand.addShortcut('F2', () => { - if (this.renderer.activeNodeList.length <= 0) { - return - } - this.show(this.renderer.activeNodeList[0]) - }) - } + /** + * @Author: 王林 + * @Date: 2021-04-24 13:27:04 + * @Desc: 事件 + */ + bindEvent() { + this.show = this.show.bind(this) + // 节点双击事件 + this.mindMap.on('node_dblclick', this.show) + // 点击事件 + this.mindMap.on('draw_click', () => { + // 隐藏文本编辑框 + this.hideEditTextBox() + }) + // 展开收缩按钮点击事件 + this.mindMap.on('expand_btn_click', () => { + this.hideEditTextBox() + }) + // 节点激活前事件 + this.mindMap.on('before_node_active', () => { + this.hideEditTextBox() + }) + // 注册编辑快捷键 + this.mindMap.keyCommand.addShortcut('F2', () => { + if (this.renderer.activeNodeList.length <= 0) { + return + } + this.show(this.renderer.activeNodeList[0]) + }) + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2022-08-16 16:27:02 - * @Desc: 注册临时快捷键 - */ - registerTmpShortcut() { - // 注册回车快捷键 - this.mindMap.keyCommand.addShortcut('Enter', () => { - this.hideEditTextBox() - }) - } + /** + * javascript comment + * @Author: 王林25 + * @Date: 2022-08-16 16:27:02 + * @Desc: 注册临时快捷键 + */ + registerTmpShortcut() { + // 注册回车快捷键 + this.mindMap.keyCommand.addShortcut('Enter', () => { + this.hideEditTextBox() + }) + } - /** - * @Author: 王林 - * @Date: 2021-04-13 22:15:56 - * @Desc: 显示文本编辑框 - */ - show(node) { - this.showEditTextBox(node, node._textData.node.node.getBoundingClientRect()) - } + /** + * @Author: 王林 + * @Date: 2021-04-13 22:15:56 + * @Desc: 显示文本编辑框 + */ + show(node) { + this.showEditTextBox(node, node._textData.node.node.getBoundingClientRect()) + } - /** - * @Author: 王林 - * @Date: 2021-04-13 22:13:02 - * @Desc: 显示文本编辑框 - */ - showEditTextBox(node, rect) { - this.mindMap.emit('before_show_text_edit') - 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;` - this.textEditNode.setAttribute('contenteditable', true) - document.body.appendChild(this.textEditNode) - } - node.style.domText(this.textEditNode, this.mindMap.view.scale) - this.textEditNode.innerHTML = node.nodeData.data.text.split(/\n/img).join('
') - this.textEditNode.style.minWidth = rect.width + 10 + 'px' - this.textEditNode.style.minHeight = rect.height + 6 + 'px' - this.textEditNode.style.left = rect.left + 'px' - this.textEditNode.style.top = rect.top + 'px' - this.textEditNode.style.display = 'block' - this.showTextEdit = true - // 选中文本 - this.selectNodeText() + /** + * @Author: 王林 + * @Date: 2021-04-13 22:13:02 + * @Desc: 显示文本编辑框 + */ + showEditTextBox(node, rect) { + this.mindMap.emit('before_show_text_edit') + 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;` + this.textEditNode.setAttribute('contenteditable', true) + document.body.appendChild(this.textEditNode) } + node.style.domText(this.textEditNode, this.mindMap.view.scale) + this.textEditNode.innerHTML = node.nodeData.data.text + .split(/\n/gim) + .join('
') + this.textEditNode.style.minWidth = rect.width + 10 + 'px' + this.textEditNode.style.minHeight = rect.height + 6 + 'px' + this.textEditNode.style.left = rect.left + 'px' + this.textEditNode.style.top = rect.top + 'px' + this.textEditNode.style.display = 'block' + this.showTextEdit = true + // 选中文本 + this.selectNodeText() + } - /** - * @Author: 王林 - * @Date: 2021-08-02 23:13:50 - * @Desc: 选中文本 - */ - selectNodeText() { - let selection = window.getSelection() - let range = document.createRange() - range.selectNodeContents(this.textEditNode) - selection.removeAllRanges() - selection.addRange(range) - } + /** + * @Author: 王林 + * @Date: 2021-08-02 23:13:50 + * @Desc: 选中文本 + */ + selectNodeText() { + let selection = window.getSelection() + let range = document.createRange() + range.selectNodeContents(this.textEditNode) + selection.removeAllRanges() + selection.addRange(range) + } - /** - * @Author: 王林 - * @Date: 2021-04-24 13:48:16 - * @Desc: 隐藏文本编辑框 - */ - hideEditTextBox() { - if (!this.showTextEdit) { - return - } - this.renderer.activeNodeList.forEach((node) => { - let str = getStrWithBrFromHtml(this.textEditNode.innerHTML) - this.mindMap.execCommand('SET_NODE_TEXT', node, str) - if (node.isGeneralization) { - // 概要节点 - node.generalizationBelongNode.updateGeneralization() - } - this.mindMap.render() - }) - this.mindMap.emit('hide_text_edit', this.textEditNode, this.renderer.activeNodeList) - this.textEditNode.style.display = 'none' - this.textEditNode.innerHTML = '' - this.textEditNode.style.fontFamily = 'inherit' - this.textEditNode.style.fontSize = 'inherit' - this.textEditNode.style.fontWeight = 'normal' - this.showTextEdit = false + /** + * @Author: 王林 + * @Date: 2021-04-24 13:48:16 + * @Desc: 隐藏文本编辑框 + */ + hideEditTextBox() { + if (!this.showTextEdit) { + return } -} \ No newline at end of file + this.renderer.activeNodeList.forEach(node => { + let str = getStrWithBrFromHtml(this.textEditNode.innerHTML) + this.mindMap.execCommand('SET_NODE_TEXT', node, str) + if (node.isGeneralization) { + // 概要节点 + node.generalizationBelongNode.updateGeneralization() + } + this.mindMap.render() + }) + this.mindMap.emit( + 'hide_text_edit', + this.textEditNode, + this.renderer.activeNodeList + ) + this.textEditNode.style.display = 'none' + this.textEditNode.innerHTML = '' + this.textEditNode.style.fontFamily = 'inherit' + this.textEditNode.style.fontSize = 'inherit' + this.textEditNode.style.fontWeight = 'normal' + this.showTextEdit = false + } +} diff --git a/simple-mind-map/src/View.js b/simple-mind-map/src/View.js index d72f8e63..ff76bed5 100644 --- a/simple-mind-map/src/View.js +++ b/simple-mind-map/src/View.js @@ -1,217 +1,218 @@ -/** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-07 14:45:24 - * @Desc: 视图操作类 +/** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-07 14:45:24 + * @Desc: 视图操作类 */ class View { - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-07 14:45:40 - * @Desc: 构造函数 - */ - constructor(opt = {}) { - this.opt = opt - this.mindMap = this.opt.mindMap - this.scale = 1 - this.sx = 0 - this.sy = 0 - this.x = 0 - this.y = 0 - this.firstDrag = true - this.setTransformData(this.mindMap.opt.viewData) - this.bind() - } + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-07 14:45:40 + * @Desc: 构造函数 + */ + constructor(opt = {}) { + this.opt = opt + this.mindMap = this.opt.mindMap + this.scale = 1 + this.sx = 0 + this.sy = 0 + this.x = 0 + this.y = 0 + this.firstDrag = true + this.setTransformData(this.mindMap.opt.viewData) + this.bind() + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-07 15:38:51 - * @Desc: 绑定 - */ - bind() { - // 快捷键 - this.mindMap.keyCommand.addShortcut('Control+=', () => { - this.enlarge() - }) - this.mindMap.keyCommand.addShortcut('Control+-', () => { - this.narrow() - }) - this.mindMap.keyCommand.addShortcut('Control+Enter', () => { - this.reset() - }) - this.mindMap.svg.on('dblclick', () => { - this.reset() - }) - // 拖动视图 - this.mindMap.event.on('mousedown', () => { - this.sx = this.x - this.sy = this.y - }) - this.mindMap.event.on('drag', (e, event) => { - if (e.ctrlKey) { - // 按住ctrl键拖动为多选 - return - } - if (this.firstDrag) { - this.firstDrag = false - // 清除激活节点 - if (this.mindMap.renderer.activeNodeList.length > 0) { - this.mindMap.execCommand('CLEAR_ACTIVE_NODE') - } - } - this.x = this.sx + event.mousemoveOffset.x - this.y = this.sy + event.mousemoveOffset.y - this.transform() - }) - this.mindMap.event.on('mouseup', () => { - this.firstDrag = true - }) - // 放大缩小视图 - this.mindMap.event.on('mousewheel', (e, dir) => { - // // 放大 - if (dir === 'down') { - this.enlarge() - } else { // 缩小 - this.narrow() - } - }) - } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-11-22 18:30:24 - * @Desc: 获取当前变换状态数据 - */ - getTransformData() { - return { - transform: this.mindMap.draw.transform(), - state: { - scale: this.scale, - x: this.x, - y: this.y, - sx: this.sx, - sy: this.sy - } + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-07 15:38:51 + * @Desc: 绑定 + */ + bind() { + // 快捷键 + this.mindMap.keyCommand.addShortcut('Control+=', () => { + this.enlarge() + }) + this.mindMap.keyCommand.addShortcut('Control+-', () => { + this.narrow() + }) + this.mindMap.keyCommand.addShortcut('Control+Enter', () => { + this.reset() + }) + this.mindMap.svg.on('dblclick', () => { + this.reset() + }) + // 拖动视图 + this.mindMap.event.on('mousedown', () => { + this.sx = this.x + this.sy = this.y + }) + this.mindMap.event.on('drag', (e, event) => { + if (e.ctrlKey) { + // 按住ctrl键拖动为多选 + return + } + if (this.firstDrag) { + this.firstDrag = false + // 清除激活节点 + if (this.mindMap.renderer.activeNodeList.length > 0) { + this.mindMap.execCommand('CLEAR_ACTIVE_NODE') } - } + } + this.x = this.sx + event.mousemoveOffset.x + this.y = this.sy + event.mousemoveOffset.y + this.transform() + }) + this.mindMap.event.on('mouseup', () => { + this.firstDrag = true + }) + // 放大缩小视图 + this.mindMap.event.on('mousewheel', (e, dir) => { + // // 放大 + if (dir === 'down') { + this.enlarge() + } else { + // 缩小 + this.narrow() + } + }) + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-11-22 19:54:17 - * @Desc: 动态设置变换状态数据 - */ - setTransformData(viewData) { - if (viewData) { - Object.keys(viewData.state).forEach((prop) => { - this[prop] = viewData.state[prop] - }) - this.mindMap.draw.transform({ - ...viewData.transform - }) - this.mindMap.emit('view_data_change', this.getTransformData()) - this.mindMap.emit('scale', this.scale) - } + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-11-22 18:30:24 + * @Desc: 获取当前变换状态数据 + */ + getTransformData() { + return { + transform: this.mindMap.draw.transform(), + state: { + scale: this.scale, + x: this.x, + y: this.y, + sx: this.sx, + sy: this.sy + } } + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-07-13 15:49:06 - * @Desc: 平移x方向 - */ - translateX(step) { - this.x += step - this.transform() + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-11-22 19:54:17 + * @Desc: 动态设置变换状态数据 + */ + setTransformData(viewData) { + if (viewData) { + Object.keys(viewData.state).forEach(prop => { + this[prop] = viewData.state[prop] + }) + this.mindMap.draw.transform({ + ...viewData.transform + }) + this.mindMap.emit('view_data_change', this.getTransformData()) + this.mindMap.emit('scale', this.scale) } + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2022-10-10 14:03:53 - * @Desc: 平移x方式到 - */ - translateXTo(x) { - this.x = x - this.transform() - } + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-07-13 15:49:06 + * @Desc: 平移x方向 + */ + translateX(step) { + this.x += step + this.transform() + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-07-13 15:48:52 - * @Desc: 平移y方向 - */ - translateY(step) { - this.y += step - this.transform() - } + /** + * javascript comment + * @Author: 王林25 + * @Date: 2022-10-10 14:03:53 + * @Desc: 平移x方式到 + */ + translateXTo(x) { + this.x = x + this.transform() + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2022-10-10 14:04:10 - * @Desc: 平移y方向到 - */ - translateYTo(y) { - this.y = y - this.transform() - } + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-07-13 15:48:52 + * @Desc: 平移y方向 + */ + translateY(step) { + this.y += step + this.transform() + } - /** - * @Author: 王林 - * @Date: 2021-07-04 17:13:14 - * @Desc: 应用变换 - */ - transform() { - this.mindMap.draw.transform({ - scale: this.scale, - // origin: 'center center', - translate: [this.x, this.y], - }) - this.mindMap.emit('view_data_change', this.getTransformData()) - } + /** + * javascript comment + * @Author: 王林25 + * @Date: 2022-10-10 14:04:10 + * @Desc: 平移y方向到 + */ + translateYTo(y) { + this.y = y + this.transform() + } - /** - * @Author: 王林 - * @Date: 2021-07-11 17:41:35 - * @Desc: 恢复 - */ - reset() { - this.scale = 1 - this.x = 0 - this.y = 0 - this.transform() - } + /** + * @Author: 王林 + * @Date: 2021-07-04 17:13:14 + * @Desc: 应用变换 + */ + transform() { + this.mindMap.draw.transform({ + scale: this.scale, + // origin: 'center center', + translate: [this.x, this.y] + }) + this.mindMap.emit('view_data_change', this.getTransformData()) + } - /** - * @Author: 王林 - * @Date: 2021-07-04 17:10:34 - * @Desc: 缩小 - */ - narrow() { - if (this.scale - this.mindMap.opt.scaleRatio > 0.1) { - this.scale -= this.mindMap.opt.scaleRatio - } else { - this.scale = 0.1 - } - this.transform() - this.mindMap.emit('scale', this.scale) - } + /** + * @Author: 王林 + * @Date: 2021-07-11 17:41:35 + * @Desc: 恢复 + */ + reset() { + this.scale = 1 + this.x = 0 + this.y = 0 + this.transform() + } - /** - * @Author: 王林 - * @Date: 2021-07-04 17:10:41 - * @Desc: 放大 - */ - enlarge() { - this.scale += this.mindMap.opt.scaleRatio - this.transform() - this.mindMap.emit('scale', this.scale) + /** + * @Author: 王林 + * @Date: 2021-07-04 17:10:34 + * @Desc: 缩小 + */ + narrow() { + if (this.scale - this.mindMap.opt.scaleRatio > 0.1) { + this.scale -= this.mindMap.opt.scaleRatio + } else { + this.scale = 0.1 } + this.transform() + this.mindMap.emit('scale', this.scale) + } + + /** + * @Author: 王林 + * @Date: 2021-07-04 17:10:41 + * @Desc: 放大 + */ + enlarge() { + this.scale += this.mindMap.opt.scaleRatio + this.transform() + this.mindMap.emit('scale', this.scale) + } } -export default View \ No newline at end of file +export default View diff --git a/simple-mind-map/src/layouts/Base.js b/simple-mind-map/src/layouts/Base.js index f07e2ff9..6ee9345a 100644 --- a/simple-mind-map/src/layouts/Base.js +++ b/simple-mind-map/src/layouts/Base.js @@ -1,248 +1,264 @@ import Node from '../Node' -import { - walk, -} from '../utils' -/** - * @Author: 王林 - * @Date: 2021-04-12 22:24:30 - * @Desc: 布局基类 +/** + * @Author: 王林 + * @Date: 2021-04-12 22:24:30 + * @Desc: 布局基类 */ class Base { - /** - * @Author: 王林 - * @Date: 2021-04-12 22:25:16 - * @Desc: 构造函数 - */ - constructor(renderer) { - // 渲染实例 - this.renderer = renderer - // 控制实例 - this.mindMap = renderer.mindMap - // 绘图对象 - this.draw = this.mindMap.draw - // 根节点 - this.root = null + /** + * @Author: 王林 + * @Date: 2021-04-12 22:25:16 + * @Desc: 构造函数 + */ + constructor(renderer) { + // 渲染实例 + this.renderer = renderer + // 控制实例 + this.mindMap = renderer.mindMap + // 绘图对象 + this.draw = this.mindMap.draw + // 根节点 + this.root = null + } + + /** + * @Author: 王林 + * @Date: 2021-04-12 22:39:50 + * @Desc: 计算节点位置 + */ + doLayout() { + throw new Error('【computed】方法为必要方法,需要子类进行重写!') + } + + /** + * @Author: 王林 + * @Date: 2021-04-12 22:41:04 + * @Desc: 连线 + */ + renderLine() { + throw new Error('【renderLine】方法为必要方法,需要子类进行重写!') + } + + /** + * @Author: 王林 + * @Date: 2021-04-12 22:42:08 + * @Desc: 定位展开收缩按钮 + */ + renderExpandBtn() { + throw new Error('【renderExpandBtn】方法为必要方法,需要子类进行重写!') + } + + /** + * @Author: 王林 + * @Date: 2022-07-30 22:49:28 + * @Desc: 概要节点 + */ + renderGeneralization() {} + + /** + * @Author: 王林 + * @Date: 2021-07-10 21:30:54 + * @Desc: 创建节点实例 + */ + createNode(data, parent, isRoot, layerIndex) { + // 创建节点 + let newNode = null + // 复用节点 + if (data && data._node && !this.renderer.reRender) { + newNode = data._node + newNode.reset() + newNode.layerIndex = layerIndex + } else { + // 创建新节点 + newNode = new Node({ + data, + uid: this.mindMap.uid++, + renderer: this.renderer, + mindMap: this.mindMap, + draw: this.draw, + layerIndex + }) + newNode.getSize() + // 数据关联实际节点 + data._node = newNode + if (data.data.isActive) { + this.renderer.addActiveNode(newNode) + } } - - /** - * @Author: 王林 - * @Date: 2021-04-12 22:39:50 - * @Desc: 计算节点位置 - */ - doLayout() { - throw new Error('【computed】方法为必要方法,需要子类进行重写!') + // 根节点 + if (isRoot) { + newNode.isRoot = true + this.root = newNode + } else { + // 互相收集 + newNode.parent = parent._node + parent._node.addChildren(newNode) } + return newNode + } - /** - * @Author: 王林 - * @Date: 2021-04-12 22:41:04 - * @Desc: 连线 - */ - renderLine() { - throw new Error('【renderLine】方法为必要方法,需要子类进行重写!') - } + /** + * @Author: 王林 + * @Date: 2021-07-16 13:48:43 + * @Desc: 定位节点到画布中间 + */ + setNodeCenter(node) { + node.left = (this.mindMap.width - node.width) / 2 + node.top = (this.mindMap.height - node.height) / 2 + } - /** - * @Author: 王林 - * @Date: 2021-04-12 22:42:08 - * @Desc: 定位展开收缩按钮 - */ - renderExpandBtn() { - throw new Error('【renderExpandBtn】方法为必要方法,需要子类进行重写!') - } + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-07 11:25:52 + * @Desc: 更新子节点属性 + */ + updateChildren(children, prop, offset) { + children.forEach(item => { + item[prop] += offset + if (item.children && item.children.length && !item.hasCustomPosition()) { + // 适配自定义位置 + this.updateChildren(item.children, prop, offset) + } + }) + } - /** - * @Author: 王林 - * @Date: 2022-07-30 22:49:28 - * @Desc: 概要节点 - */ - renderGeneralization() {} + /** + * @Author: 王林 + * @Date: 2021-04-11 15:05:01 + * @Desc: 二次贝塞尔曲线 + */ + quadraticCurvePath(x1, y1, x2, y2) { + let cx = x1 + (x2 - x1) * 0.2 + let cy = y1 + (y2 - y1) * 0.8 + return `M ${x1},${y1} Q ${cx},${cy} ${x2},${y2}` + } - /** - * @Author: 王林 - * @Date: 2021-07-10 21:30:54 - * @Desc: 创建节点实例 - */ - createNode(data, parent, isRoot, layerIndex) { - // 创建节点 - let newNode = null - // 复用节点 - if (data && data._node && !this.renderer.reRender) { - newNode = data._node - newNode.reset() - newNode.layerIndex = layerIndex - } else {// 创建新节点 - newNode = new Node({ - data, - uid: this.mindMap.uid++, - renderer: this.renderer, - mindMap: this.mindMap, - draw: this.draw, - layerIndex - }) - newNode.getSize() - // 数据关联实际节点 - data._node = newNode - if (data.data.isActive) { - this.renderer.addActiveNode(newNode) - } - } - // 根节点 - if (isRoot) { - newNode.isRoot = true - this.root = newNode - } else { - // 互相收集 - newNode.parent = parent._node - parent._node.addChildren(newNode) - } - return newNode; - } + /** + * @Author: 王林 + * @Date: 2021-04-11 15:05:18 + * @Desc: 三次贝塞尔曲线 + */ + cubicBezierPath(x1, y1, x2, y2) { + let cx1 = x1 + (x2 - x1) / 2 + let cy1 = y1 + let cx2 = cx1 + let cy2 = y2 + return `M ${x1},${y1} C ${cx1},${cy1} ${cx2},${cy2} ${x2},${y2}` + } - /** - * @Author: 王林 - * @Date: 2021-07-16 13:48:43 - * @Desc: 定位节点到画布中间 - */ - setNodeCenter(node) { - node.left = (this.mindMap.width - node.width) / 2 - node.top = (this.mindMap.height - node.height) / 2 - } + /** + * @Author: 王林 + * @Date: 2021-06-27 19:00:07 + * @Desc: 获取节点的marginX + */ + getMarginX(layerIndex) { + return layerIndex === 1 + ? this.mindMap.themeConfig.second.marginX + : this.mindMap.themeConfig.node.marginX + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-07 11:25:52 - * @Desc: 更新子节点属性 - */ - updateChildren(children, prop, offset) { - children.forEach((item) => { - item[prop] += offset - if (item.children && item.children.length && !item.hasCustomPosition()) {// 适配自定义位置 - this.updateChildren(item.children, prop, offset) - } + /** + * @Author: 王林 + * @Date: 2021-04-11 15:34:20 + * @Desc: 获取节点的marginY + */ + getMarginY(layerIndex) { + return layerIndex === 1 + ? this.mindMap.themeConfig.second.marginY + : this.mindMap.themeConfig.node.marginY + } + + /** + * @Author: 王林 + * @Date: 2022-07-31 20:53:12 + * @Desc: 获取节点包括概要在内的宽度 + */ + getNodeWidthWithGeneralization(node) { + return Math.max( + node.width, + node.checkHasGeneralization() ? node._generalizationNodeWidth : 0 + ) + } + + /** + * @Author: 王林 + * @Date: 2022-07-31 20:53:12 + * @Desc: 获取节点包括概要在内的高度 + */ + getNodeHeightWithGeneralization(node) { + return Math.max( + node.height, + node.checkHasGeneralization() ? node._generalizationNodeHeight : 0 + ) + } + + /** + * @Author: 王林 + * @Date: 2022-07-31 09:14:03 + * @Desc: 获取节点的边界值 + * dir:生长方向,h(水平)、v(垂直) + * isLeft:是否向左生长 + */ + getNodeBoundaries(node, dir) { + let { generalizationLineMargin, generalizationNodeMargin } = + this.mindMap.themeConfig + let walk = root => { + let _left = Infinity + let _right = -Infinity + let _top = Infinity + let _bottom = -Infinity + if (root.children && root.children.length > 0) { + root.children.forEach(child => { + let { left, right, top, bottom } = walk(child) + // 概要内容的宽度 + let generalizationWidth = + child.checkHasGeneralization() && child.nodeData.data.expand + ? child._generalizationNodeWidth + generalizationNodeMargin + : 0 + // 概要内容的高度 + let generalizationHeight = + child.checkHasGeneralization() && child.nodeData.data.expand + ? child._generalizationNodeHeight + generalizationNodeMargin + : 0 + if (left - (dir === 'h' ? generalizationWidth : 0) < _left) { + _left = left - (dir === 'h' ? generalizationWidth : 0) + } + if (right + (dir === 'h' ? generalizationWidth : 0) > _right) { + _right = right + (dir === 'h' ? generalizationWidth : 0) + } + if (top < _top) { + _top = top + } + if (bottom + (dir === 'v' ? generalizationHeight : 0) > _bottom) { + _bottom = bottom + (dir === 'v' ? generalizationHeight : 0) + } }) + } + let cur = { + left: root.left, + right: root.left + root.width, + top: root.top, + bottom: root.top + root.height + } + return { + left: cur.left < _left ? cur.left : _left, + right: cur.right > _right ? cur.right : _right, + top: cur.top < _top ? cur.top : _top, + bottom: cur.bottom > _bottom ? cur.bottom : _bottom + } } - - /** - * @Author: 王林 - * @Date: 2021-04-11 15:05:01 - * @Desc: 二次贝塞尔曲线 - */ - quadraticCurvePath(x1, y1, x2, y2) { - let cx = x1 + (x2 - x1) * 0.2 - let cy = y1 + (y2 - y1) * 0.8 - return `M ${x1},${y1} Q ${cx},${cy} ${x2},${y2}` - } - - /** - * @Author: 王林 - * @Date: 2021-04-11 15:05:18 - * @Desc: 三次贝塞尔曲线 - */ - cubicBezierPath(x1, y1, x2, y2) { - let cx1 = x1 + (x2 - x1) / 2 - let cy1 = y1 - let cx2 = cx1 - let cy2 = y2 - return `M ${x1},${y1} C ${cx1},${cy1} ${cx2},${cy2} ${x2},${y2}` - } - - /** - * @Author: 王林 - * @Date: 2021-06-27 19:00:07 - * @Desc: 获取节点的marginX - */ - getMarginX(layerIndex) { - return layerIndex === 1 ? this.mindMap.themeConfig.second.marginX : this.mindMap.themeConfig.node.marginX; - } - - /** - * @Author: 王林 - * @Date: 2021-04-11 15:34:20 - * @Desc: 获取节点的marginY - */ - getMarginY(layerIndex) { - return layerIndex === 1 ? this.mindMap.themeConfig.second.marginY : this.mindMap.themeConfig.node.marginY; - } - - /** - * @Author: 王林 - * @Date: 2022-07-31 20:53:12 - * @Desc: 获取节点包括概要在内的宽度 - */ - getNodeWidthWithGeneralization(node) { - return Math.max(node.width, node.checkHasGeneralization() ? node._generalizationNodeWidth : 0) - } - - /** - * @Author: 王林 - * @Date: 2022-07-31 20:53:12 - * @Desc: 获取节点包括概要在内的高度 - */ - getNodeHeightWithGeneralization(node) { - return Math.max(node.height, node.checkHasGeneralization() ? node._generalizationNodeHeight : 0) - } - - /** - * @Author: 王林 - * @Date: 2022-07-31 09:14:03 - * @Desc: 获取节点的边界值 - * dir:生长方向,h(水平)、v(垂直) - * isLeft:是否向左生长 - */ - getNodeBoundaries(node, dir, isLeft) { - let { generalizationLineMargin, generalizationNodeMargin } = this.mindMap.themeConfig - let walk = (root) => { - let _left = Infinity - let _right = -Infinity - let _top = Infinity - let _bottom = -Infinity - if (root.children && root.children.length > 0) { - root.children.forEach((child) => { - let {left, right, top, bottom} = walk(child) - // 概要内容的宽度 - let generalizationWidth = child.checkHasGeneralization() && child.nodeData.data.expand ? child._generalizationNodeWidth + generalizationNodeMargin : 0 - // 概要内容的高度 - let generalizationHeight = child.checkHasGeneralization() && child.nodeData.data.expand ? child._generalizationNodeHeight + generalizationNodeMargin : 0 - if (left - (dir === 'h' ? generalizationWidth : 0) < _left) { - _left = left - (dir === 'h' ? generalizationWidth : 0) - } - if (right + (dir === 'h' ? generalizationWidth : 0) > _right) { - _right = right + (dir === 'h' ? generalizationWidth : 0) - } - if (top < _top) { - _top = top - } - if (bottom + (dir === 'v' ? generalizationHeight : 0) > _bottom) { - _bottom = bottom + (dir === 'v' ? generalizationHeight : 0) - } - }) - } - let cur = { - left: root.left, - right: root.left + root.width, - top: root.top, - bottom: root.top + root.height - } - return { - left: cur.left < _left ? cur.left : _left, - right: cur.right > _right ? cur.right : _right, - top: cur.top < _top ? cur.top : _top, - bottom: cur.bottom > _bottom ? cur.bottom : _bottom - } - } - let {left, right, top, bottom} = walk(node) - return { - left, - right, - top, - bottom, - generalizationLineMargin, - generalizationNodeMargin - }; + let { left, right, top, bottom } = walk(node) + return { + left, + right, + top, + bottom, + generalizationLineMargin, + generalizationNodeMargin } + } } -export default Base \ No newline at end of file +export default Base diff --git a/simple-mind-map/src/layouts/CatalogOrganization.js b/simple-mind-map/src/layouts/CatalogOrganization.js index ec1a4fbb..46ae5e65 100644 --- a/simple-mind-map/src/layouts/CatalogOrganization.js +++ b/simple-mind-map/src/layouts/CatalogOrganization.js @@ -1,386 +1,430 @@ -import Base from './Base'; -import { - walk, - asyncRun -} from '../utils' +import Base from './Base' +import { walk, asyncRun } from '../utils' -/** - * @Author: 王林 - * @Date: 2021-04-12 22:25:58 - * @Desc: 目录组织图 +/** + * @Author: 王林 + * @Date: 2021-04-12 22:25:58 + * @Desc: 目录组织图 */ class CatalogOrganization extends Base { - /** - * @Author: 王林 - * @Date: 2021-04-12 22:26:31 - * @Desc: 构造函数 - */ - constructor(opt = {}) { - super(opt) - } + /** + * @Author: 王林 + * @Date: 2021-04-12 22:26:31 + * @Desc: 构造函数 + */ + constructor(opt = {}) { + super(opt) + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-06 14:04:20 - * @Desc: 布局 - */ - doLayout(callback) { - let task = [() => { - this.computedBaseValue() - }, () => { - this.computedLeftTopValue() - }, () => { - this.adjustLeftTopValue() - }, () => { - callback(this.root) - }] - asyncRun(task) - } + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-06 14:04:20 + * @Desc: 布局 + */ + doLayout(callback) { + let task = [ + () => { + this.computedBaseValue() + }, + () => { + this.computedLeftTopValue() + }, + () => { + this.adjustLeftTopValue() + }, + () => { + callback(this.root) + } + ] + asyncRun(task) + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-08 09:49:32 - * @Desc: 遍历数据计算节点的left、width、height - */ - computedBaseValue() { - walk(this.renderer.renderTree, null, (cur, parent, isRoot, layerIndex) => { - let newNode = this.createNode(cur, parent, isRoot, layerIndex) - // 根节点定位在画布中心位置 - if (isRoot) { - this.setNodeCenter(newNode) - } else { - // 非根节点 - if (parent._node.isRoot) { - newNode.top = parent._node.top + parent._node.height + this.getMarginX(layerIndex) - } - } - if (!cur.data.expand) { - return true; - } - }, (cur, parent, isRoot, layerIndex) => { - if (isRoot) { - let len = cur.data.expand === false ? 0 : cur._node.children.length - cur._node.childrenAreaWidth = len ? cur._node.children.reduce((h, item) => { - return h + item.width - }, 0) + (len + 1) * this.getMarginX(layerIndex + 1) : 0 - } - }, true, 0) - } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-08 09:59:25 - * @Desc: 遍历节点树计算节点的left、top - */ - computedLeftTopValue() { - walk(this.root, null, (node, parent, isRoot, layerIndex) => { - if (node.nodeData.data.expand && node.children && node.children.length) { - let marginX = this.getMarginX(layerIndex + 1) - let marginY = this.getMarginY(layerIndex + 1) - if (isRoot) { - let left = node.left + node.width / 2 - node.childrenAreaWidth / 2 - let totalLeft = left + marginX - node.children.forEach((cur) => { - cur.left = totalLeft - totalLeft += cur.width + marginX - }) - } else { - let totalTop = node.top + node.height + marginY + node.expandBtnSize - node.children.forEach((cur) => { - cur.left = node.left + node.width * 0.5 - cur.top = totalTop - totalTop += cur.height + marginY + node.expandBtnSize - }) - } - } - }, null, true) - } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-08 10:04:05 - * @Desc: 调整节点left、top - */ - adjustLeftTopValue() { - walk(this.root, null, (node, parent, isRoot, layerIndex) => { - if (!node.nodeData.data.expand) { - return; - } - // 调整left - if (parent && parent.isRoot) { - let areaWidth = this.getNodeAreaWidth(node) - let difference = areaWidth - node.width - if (difference > 0) { - this.updateBrothersLeft(node, difference / 2) - } - } - // 调整top - let len = node.children.length - if (parent && !parent.isRoot && len > 0) { - let marginY = this.getMarginY(layerIndex + 1) - let totalHeight = node.children.reduce((h, item) => { - return h + item.height - }, 0) + (len + 1) * marginY + len * node.expandBtnSize - this.updateBrothersTop(node, totalHeight) - } - }, null, true) - } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-12 18:55:03 - * @Desc: 递归计算节点的宽度 - */ - getNodeAreaWidth(node) { - let widthArr = [] - let loop = (node, width) => { - if (node.children.length) { - width += node.width / 2 - node.children.forEach((item) => { - loop(item, width) - }) - } else { - width += node.width - widthArr.push(width) - } - } - loop(node, 0) - return Math.max(...widthArr) - } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-07-13 11:12:51 - * @Desc: 调整兄弟节点的left - */ - updateBrothersLeft(node, addWidth) { - if (node.parent) { - let childrenList = node.parent.children - let index = childrenList.findIndex((item) => { - return item === node - }) - // 存在大于一个节点时,第一个或最后一个节点自身也需要移动,否则两边不对称 - if ((index === 0 || index === childrenList.length - 1) && childrenList.length > 1) { - let _offset = index === 0 ? -addWidth : addWidth - node.left += _offset - if (node.children && node.children.length && !node.hasCustomPosition()) { - this.updateChildren(node.children, 'left', _offset) - } - } - childrenList.forEach((item, _index) => { - if (item.hasCustomPosition()) {// 适配自定义位置 - return - } - let _offset = 0 - if (_index < index) { // 左边的节点往左移 - _offset = -addWidth - } else if (_index > index) { // 右边的节点往右移 - _offset = addWidth - } - item.left += _offset - // 同步更新子节点的位置 - if (item.children && item.children.length) { - this.updateChildren(item.children, 'left', _offset) - } - }) - // 更新父节点的位置 - this.updateBrothersLeft(node.parent, addWidth) - } - } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-07 14:26:03 - * @Desc: 调整兄弟节点的top - */ - updateBrothersTop(node, addHeight) { - if (node.parent && !node.parent.isRoot) { - let childrenList = node.parent.children - let index = childrenList.findIndex((item) => { - return item === node - }) - childrenList.forEach((item, _index) => { - if (item.hasCustomPosition()) {// 适配自定义位置 - return - } - let _offset = 0 - // 下面的节点往下移 - if (_index > index) { - _offset = addHeight - } - item.top += _offset - // 同步更新子节点的位置 - if (item.children && item.children.length) { - this.updateChildren(item.children, 'top', _offset) - } - }) - // 更新父节点的位置 - this.updateBrothersTop(node.parent, addHeight) - } - } - - /** - * @Author: 王林 - * @Date: 2021-04-11 14:42:48 - * @Desc: 绘制连线,连接该节点到其子节点 - */ - renderLine(node, lines, style) { - if (node.children.length <= 0) { - return []; - } - let { - left, - top, - width, - height, - expandBtnSize - } = node - let len = node.children.length - let marginX = this.getMarginX(node.layerIndex + 1) - if (node.isRoot) { - // 根节点 - let x1 = left + width / 2 - let y1 = top + height - let s1 = marginX * 0.7 - let minx = Infinity - let maxx = -Infinity - node.children.forEach((item, index) => { - let x2 = item.left +item.width / 2 - let y2 = item.top - if (x2 < minx) { - minx = x2 - } - if (x2 > maxx) { - maxx = x2 - } - let path = `M ${x2},${y1 + s1} L ${x2},${y1 + s1 > y2 ? y2 + item.height : y2}` - // 竖线 - lines[index].plot(path) - style && style(lines[index], item) - }) - minx = Math.min(minx, x1) - maxx = Math.max(maxx, x1) - // 父节点的竖线 - let line1 = this.draw.path() - node.style.line(line1) - line1.plot(`M ${x1},${y1} L ${x1},${y1 + s1}`) - node._lines.push(line1) - style && style(line1, node) - // 水平线 - if (len > 0) { - let lin2 = this.draw.path() - node.style.line(lin2) - lin2.plot(`M ${minx},${y1 + s1} L ${maxx},${y1 + s1}`) - node._lines.push(lin2) - style && style(lin2, node) - } + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-08 09:49:32 + * @Desc: 遍历数据计算节点的left、width、height + */ + computedBaseValue() { + walk( + this.renderer.renderTree, + null, + (cur, parent, isRoot, layerIndex) => { + let newNode = this.createNode(cur, parent, isRoot, layerIndex) + // 根节点定位在画布中心位置 + if (isRoot) { + this.setNodeCenter(newNode) } else { - // 非根节点 - let y1 = top + height - let maxy = -Infinity - let x2 = node.left + node.width * 0.3 - node.children.forEach((item, index) => { - // 为了适配自定义位置,下面做了各种位置的兼容 - let y2 = item.top + item.height / 2 - if (y2 > maxy) { - maxy = y2 - } - // 水平线 - let path = '' - let _left = item.left - let _isLeft = item.left + item.width < x2 - let _isXCenter = false - if (_isLeft) { - // 水平位置在父节点左边 - _left = item.left + item.width - } else if (item.left < x2 && item.left + item.width > x2) { - // 水平位置在父节点之间 - _isXCenter = true - y2 = item.top - maxy = y2 - } - if (y2 > top && y2 < y1) { - // 自定义位置的情况:垂直位置节点在父节点之间 - path = `M ${_isLeft ? node.left : node.left + node.width},${y2} L ${_left},${y2}` - } else if (y2 < y1) { - // 自定义位置的情况:垂直位置节点在父节点上面 - if (_isXCenter) { - y2 = item.top + item.height - _left = x2 - } - path = `M ${x2},${top} L ${x2},${y2} L ${_left},${y2}` - } else { - if (_isXCenter) { - _left = x2 - } - path = `M ${x2},${y2} L ${_left},${y2}` - } - lines[index].plot(path) - style && style(lines[index], item) + // 非根节点 + if (parent._node.isRoot) { + newNode.top = + parent._node.top + + parent._node.height + + this.getMarginX(layerIndex) + } + } + if (!cur.data.expand) { + return true + } + }, + (cur, parent, isRoot, layerIndex) => { + if (isRoot) { + let len = cur.data.expand === false ? 0 : cur._node.children.length + cur._node.childrenAreaWidth = len + ? cur._node.children.reduce((h, item) => { + return h + item.width + }, 0) + + (len + 1) * this.getMarginX(layerIndex + 1) + : 0 + } + }, + true, + 0 + ) + } + + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-08 09:59:25 + * @Desc: 遍历节点树计算节点的left、top + */ + computedLeftTopValue() { + walk( + this.root, + null, + (node, parent, isRoot, layerIndex) => { + if ( + node.nodeData.data.expand && + node.children && + node.children.length + ) { + let marginX = this.getMarginX(layerIndex + 1) + let marginY = this.getMarginY(layerIndex + 1) + if (isRoot) { + let left = node.left + node.width / 2 - node.childrenAreaWidth / 2 + let totalLeft = left + marginX + node.children.forEach(cur => { + cur.left = totalLeft + totalLeft += cur.width + marginX }) - // 竖线 - if (len > 0) { - let lin2 = this.draw.path() - expandBtnSize = len > 0 ? expandBtnSize : 0 - node.style.line(lin2) - if (maxy < y1 + expandBtnSize) { - lin2.hide() - } else { - lin2.plot(`M ${x2},${y1 + expandBtnSize} L ${x2},${maxy}`) - lin2.show() - } - node._lines.push(lin2) - style && style(lin2, node) - } + } else { + let totalTop = node.top + node.height + marginY + node.expandBtnSize + node.children.forEach(cur => { + cur.left = node.left + node.width * 0.5 + cur.top = totalTop + totalTop += cur.height + marginY + node.expandBtnSize + }) + } } - } + }, + null, + true + ) + } - /** - * @Author: 王林 - * @Date: 2021-04-11 19:54:26 - * @Desc: 渲染按钮 - */ - renderExpandBtn(node, btn) { - let { - width, - height, - expandBtnSize, - isRoot - } = node - if (!isRoot) { - let { - translateX, - translateY - } = btn.transform() - btn.translate(width * 0.3 - expandBtnSize / 2 - translateX, height + expandBtnSize / 2 - translateY) + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-08 10:04:05 + * @Desc: 调整节点left、top + */ + adjustLeftTopValue() { + walk( + this.root, + null, + (node, parent, isRoot, layerIndex) => { + if (!node.nodeData.data.expand) { + return } - } + // 调整left + if (parent && parent.isRoot) { + let areaWidth = this.getNodeAreaWidth(node) + let difference = areaWidth - node.width + if (difference > 0) { + this.updateBrothersLeft(node, difference / 2) + } + } + // 调整top + let len = node.children.length + if (parent && !parent.isRoot && len > 0) { + let marginY = this.getMarginY(layerIndex + 1) + let totalHeight = + node.children.reduce((h, item) => { + return h + item.height + }, 0) + + (len + 1) * marginY + + len * node.expandBtnSize + this.updateBrothersTop(node, totalHeight) + } + }, + null, + true + ) + } - /** - * @Author: 王林 - * @Date: 2022-07-30 08:30:35 - * @Desc: 创建概要节点 - */ - renderGeneralization(node, gLine, gNode) { - let { top, bottom, right, generalizationLineMargin, generalizationNodeMargin } = this.getNodeBoundaries(node, 'h') - let x1 = right + generalizationLineMargin - let y1 = top - let x2 = right + generalizationLineMargin - let y2 = bottom - let cx = x1 + 20 - let cy = y1 + (y2 - y1) / 2 - let path = `M ${x1},${y1} Q ${cx},${cy} ${x2},${y2}` - gLine.plot(path) - gNode.left = right + generalizationNodeMargin - gNode.top = top + (bottom - top - gNode.height) / 2 + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-12 18:55:03 + * @Desc: 递归计算节点的宽度 + */ + getNodeAreaWidth(node) { + let widthArr = [] + let loop = (node, width) => { + if (node.children.length) { + width += node.width / 2 + node.children.forEach(item => { + loop(item, width) + }) + } else { + width += node.width + widthArr.push(width) + } } + loop(node, 0) + return Math.max(...widthArr) + } + + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-07-13 11:12:51 + * @Desc: 调整兄弟节点的left + */ + updateBrothersLeft(node, addWidth) { + if (node.parent) { + let childrenList = node.parent.children + let index = childrenList.findIndex(item => { + return item === node + }) + // 存在大于一个节点时,第一个或最后一个节点自身也需要移动,否则两边不对称 + if ( + (index === 0 || index === childrenList.length - 1) && + childrenList.length > 1 + ) { + let _offset = index === 0 ? -addWidth : addWidth + node.left += _offset + if ( + node.children && + node.children.length && + !node.hasCustomPosition() + ) { + this.updateChildren(node.children, 'left', _offset) + } + } + childrenList.forEach((item, _index) => { + if (item.hasCustomPosition()) { + // 适配自定义位置 + return + } + let _offset = 0 + if (_index < index) { + // 左边的节点往左移 + _offset = -addWidth + } else if (_index > index) { + // 右边的节点往右移 + _offset = addWidth + } + item.left += _offset + // 同步更新子节点的位置 + if (item.children && item.children.length) { + this.updateChildren(item.children, 'left', _offset) + } + }) + // 更新父节点的位置 + this.updateBrothersLeft(node.parent, addWidth) + } + } + + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-07 14:26:03 + * @Desc: 调整兄弟节点的top + */ + updateBrothersTop(node, addHeight) { + if (node.parent && !node.parent.isRoot) { + let childrenList = node.parent.children + let index = childrenList.findIndex(item => { + return item === node + }) + childrenList.forEach((item, _index) => { + if (item.hasCustomPosition()) { + // 适配自定义位置 + return + } + let _offset = 0 + // 下面的节点往下移 + if (_index > index) { + _offset = addHeight + } + item.top += _offset + // 同步更新子节点的位置 + if (item.children && item.children.length) { + this.updateChildren(item.children, 'top', _offset) + } + }) + // 更新父节点的位置 + this.updateBrothersTop(node.parent, addHeight) + } + } + + /** + * @Author: 王林 + * @Date: 2021-04-11 14:42:48 + * @Desc: 绘制连线,连接该节点到其子节点 + */ + renderLine(node, lines, style) { + if (node.children.length <= 0) { + return [] + } + let { left, top, width, height, expandBtnSize } = node + let len = node.children.length + let marginX = this.getMarginX(node.layerIndex + 1) + if (node.isRoot) { + // 根节点 + let x1 = left + width / 2 + let y1 = top + height + let s1 = marginX * 0.7 + let minx = Infinity + let maxx = -Infinity + node.children.forEach((item, index) => { + let x2 = item.left + item.width / 2 + let y2 = item.top + if (x2 < minx) { + minx = x2 + } + if (x2 > maxx) { + maxx = x2 + } + let path = `M ${x2},${y1 + s1} L ${x2},${ + y1 + s1 > y2 ? y2 + item.height : y2 + }` + // 竖线 + lines[index].plot(path) + style && style(lines[index], item) + }) + minx = Math.min(minx, x1) + maxx = Math.max(maxx, x1) + // 父节点的竖线 + let line1 = this.draw.path() + node.style.line(line1) + line1.plot(`M ${x1},${y1} L ${x1},${y1 + s1}`) + node._lines.push(line1) + style && style(line1, node) + // 水平线 + if (len > 0) { + let lin2 = this.draw.path() + node.style.line(lin2) + lin2.plot(`M ${minx},${y1 + s1} L ${maxx},${y1 + s1}`) + node._lines.push(lin2) + style && style(lin2, node) + } + } else { + // 非根节点 + let y1 = top + height + let maxy = -Infinity + let x2 = node.left + node.width * 0.3 + node.children.forEach((item, index) => { + // 为了适配自定义位置,下面做了各种位置的兼容 + let y2 = item.top + item.height / 2 + if (y2 > maxy) { + maxy = y2 + } + // 水平线 + let path = '' + let _left = item.left + let _isLeft = item.left + item.width < x2 + let _isXCenter = false + if (_isLeft) { + // 水平位置在父节点左边 + _left = item.left + item.width + } else if (item.left < x2 && item.left + item.width > x2) { + // 水平位置在父节点之间 + _isXCenter = true + y2 = item.top + maxy = y2 + } + if (y2 > top && y2 < y1) { + // 自定义位置的情况:垂直位置节点在父节点之间 + path = `M ${ + _isLeft ? node.left : node.left + node.width + },${y2} L ${_left},${y2}` + } else if (y2 < y1) { + // 自定义位置的情况:垂直位置节点在父节点上面 + if (_isXCenter) { + y2 = item.top + item.height + _left = x2 + } + path = `M ${x2},${top} L ${x2},${y2} L ${_left},${y2}` + } else { + if (_isXCenter) { + _left = x2 + } + path = `M ${x2},${y2} L ${_left},${y2}` + } + lines[index].plot(path) + style && style(lines[index], item) + }) + // 竖线 + if (len > 0) { + let lin2 = this.draw.path() + expandBtnSize = len > 0 ? expandBtnSize : 0 + node.style.line(lin2) + if (maxy < y1 + expandBtnSize) { + lin2.hide() + } else { + lin2.plot(`M ${x2},${y1 + expandBtnSize} L ${x2},${maxy}`) + lin2.show() + } + node._lines.push(lin2) + style && style(lin2, node) + } + } + } + + /** + * @Author: 王林 + * @Date: 2021-04-11 19:54:26 + * @Desc: 渲染按钮 + */ + renderExpandBtn(node, btn) { + let { width, height, expandBtnSize, isRoot } = node + if (!isRoot) { + let { translateX, translateY } = btn.transform() + btn.translate( + width * 0.3 - expandBtnSize / 2 - translateX, + height + expandBtnSize / 2 - translateY + ) + } + } + + /** + * @Author: 王林 + * @Date: 2022-07-30 08:30:35 + * @Desc: 创建概要节点 + */ + renderGeneralization(node, gLine, gNode) { + let { + top, + bottom, + right, + generalizationLineMargin, + generalizationNodeMargin + } = this.getNodeBoundaries(node, 'h') + let x1 = right + generalizationLineMargin + let y1 = top + let x2 = right + generalizationLineMargin + let y2 = bottom + let cx = x1 + 20 + let cy = y1 + (y2 - y1) / 2 + let path = `M ${x1},${y1} Q ${cx},${cy} ${x2},${y2}` + gLine.plot(path) + gNode.left = right + generalizationNodeMargin + gNode.top = top + (bottom - top - gNode.height) / 2 + } } -export default CatalogOrganization \ No newline at end of file +export default CatalogOrganization diff --git a/simple-mind-map/src/layouts/LogicalStructure.js b/simple-mind-map/src/layouts/LogicalStructure.js index 542fe081..d4e9322e 100644 --- a/simple-mind-map/src/layouts/LogicalStructure.js +++ b/simple-mind-map/src/layouts/LogicalStructure.js @@ -1,287 +1,308 @@ -import Base from './Base'; -import { - walk, - asyncRun -} from '../utils' +import Base from './Base' +import { walk, asyncRun } from '../utils' -/** - * @Author: 王林 - * @Date: 2021-04-12 22:25:58 - * @Desc: 逻辑结构图 +/** + * @Author: 王林 + * @Date: 2021-04-12 22:25:58 + * @Desc: 逻辑结构图 */ class LogicalStructure extends Base { - /** - * @Author: 王林 - * @Date: 2021-04-12 22:26:31 - * @Desc: 构造函数 - */ - constructor(opt = {}) { - super(opt) - } + /** + * @Author: 王林 + * @Date: 2021-04-12 22:26:31 + * @Desc: 构造函数 + */ + constructor(opt = {}) { + super(opt) + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-06 14:04:20 - * @Desc: 布局 - */ - doLayout(callback) { - let task = [() => { - this.computedBaseValue() - }, () => { - this.computedTopValue() - }, () => { - this.adjustTopValue() - }, () => { - callback(this.root) - }] - asyncRun(task) - } + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-06 14:04:20 + * @Desc: 布局 + */ + doLayout(callback) { + let task = [ + () => { + this.computedBaseValue() + }, + () => { + this.computedTopValue() + }, + () => { + this.adjustTopValue() + }, + () => { + callback(this.root) + } + ] + asyncRun(task) + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-08 09:49:32 - * @Desc: 遍历数据计算节点的left、width、height - */ - computedBaseValue() { - walk(this.renderer.renderTree, null, (cur, parent, isRoot, layerIndex) => { - let newNode = this.createNode(cur, parent, isRoot, layerIndex) - // 根节点定位在画布中心位置 - if (isRoot) { - this.setNodeCenter(newNode) - } else { - // 非根节点 - // 定位到父节点右侧 - newNode.left = parent._node.left + parent._node.width + this.getMarginX(layerIndex) - } - if (!cur.data.expand) { - return true; - } - }, (cur, parent, isRoot, layerIndex) => { - // 返回时计算节点的areaHeight,也就是子节点所占的高度之和,包括外边距 - let len = cur.data.expand === false ? 0 : cur._node.children.length - cur._node.childrenAreaHeight = len ? cur._node.children.reduce((h, item) => { - return h + item.height - }, 0) + (len + 1) * this.getMarginY(layerIndex + 1) : 0 - }, true, 0) - } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-08 09:59:25 - * @Desc: 遍历节点树计算节点的top - */ - computedTopValue() { - walk(this.root, null, (node, parent, isRoot, layerIndex) => { - if (node.nodeData.data.expand && node.children && node.children.length) { - let marginY = this.getMarginY(layerIndex + 1) - // 第一个子节点的top值 = 该节点中心的top值 - 子节点的高度之和的一半 - let top = node.top + node.height / 2 - node.childrenAreaHeight / 2 - let totalTop = top + marginY - node.children.forEach((cur) => { - cur.top = totalTop - totalTop += cur.height + marginY - }) - } - }, null, true) - } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-08 10:04:05 - * @Desc: 调整节点top - */ - adjustTopValue() { - walk(this.root, null, (node, parent, isRoot, layerIndex) => { - if (!node.nodeData.data.expand) { - return; - } - // 判断子节点所占的高度之和是否大于该节点自身,大于则需要调整位置 - let difference = node.childrenAreaHeight - this.getMarginY(layerIndex + 1) * 2 - node.height - if (difference > 0) { - this.updateBrothers(node, difference / 2) - } - }, null, true) - } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-07 14:26:03 - * @Desc: 更新兄弟节点的top - */ - updateBrothers(node, addHeight) { - if (node.parent) { - let childrenList = node.parent.children - let index = childrenList.findIndex((item) => { - return item === node - }) - childrenList.forEach((item, _index) => { - if (item === node || item.hasCustomPosition()) {// 适配自定义位置 - return - } - let _offset = 0 - // 上面的节点往上移 - if (_index < index) { - _offset = -addHeight - } else if (_index > index) { // 下面的节点往下移 - _offset = addHeight - } - item.top += _offset - // 同步更新子节点的位置 - if (item.children && item.children.length) { - this.updateChildren(item.children, 'top', _offset) - } - }) - // 更新父节点的位置 - this.updateBrothers(node.parent, addHeight) - } - } - - /** - * @Author: 王林 - * @Date: 2021-04-11 14:42:48 - * @Desc: 绘制连线,连接该节点到其子节点 - */ - renderLine(node, lines, style, lineStyle) { - if (lineStyle === 'curve') { - this.renderLineCurve(node, lines, style) - } else if (lineStyle === 'direct') { - this.renderLineDirect(node, lines, style) + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-08 09:49:32 + * @Desc: 遍历数据计算节点的left、width、height + */ + computedBaseValue() { + walk( + this.renderer.renderTree, + null, + (cur, parent, isRoot, layerIndex) => { + let newNode = this.createNode(cur, parent, isRoot, layerIndex) + // 根节点定位在画布中心位置 + if (isRoot) { + this.setNodeCenter(newNode) } else { - this.renderLineStraight(node, lines, style) + // 非根节点 + // 定位到父节点右侧 + newNode.left = + parent._node.left + parent._node.width + this.getMarginX(layerIndex) } - } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2022-09-30 14:17:30 - * @Desc: 直线风格连线 - */ - renderLineStraight(node, lines, style) { - if (node.children.length <= 0) { - return []; + if (!cur.data.expand) { + return true } - let { - left, - top, - width, - height, - expandBtnSize - } = node - let marginX = this.getMarginX(node.layerIndex + 1) - let s1 = (marginX - expandBtnSize) * 0.6 - node.children.forEach((item, index) => { - let x1 = node.layerIndex === 0 ? left + width : left + width + expandBtnSize - let y1 = top + height / 2 - let x2 = item.left - let y2 = item.top + item.height / 2 - let path = `M ${x1},${y1} L ${x1 + s1},${y1} L ${x1 + s1},${y2} L ${x2},${y2}` - lines[index].plot(path) - style && style(lines[index], item) - }) - } + }, + (cur, parent, isRoot, layerIndex) => { + // 返回时计算节点的areaHeight,也就是子节点所占的高度之和,包括外边距 + let len = cur.data.expand === false ? 0 : cur._node.children.length + cur._node.childrenAreaHeight = len + ? cur._node.children.reduce((h, item) => { + return h + item.height + }, 0) + + (len + 1) * this.getMarginY(layerIndex + 1) + : 0 + }, + true, + 0 + ) + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2022-09-30 14:34:41 - * @Desc: 直连风格 - */ - renderLineDirect(node, lines, style) { - if (node.children.length <= 0) { - return []; + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-08 09:59:25 + * @Desc: 遍历节点树计算节点的top + */ + computedTopValue() { + walk( + this.root, + null, + (node, parent, isRoot, layerIndex) => { + if ( + node.nodeData.data.expand && + node.children && + node.children.length + ) { + let marginY = this.getMarginY(layerIndex + 1) + // 第一个子节点的top值 = 该节点中心的top值 - 子节点的高度之和的一半 + let top = node.top + node.height / 2 - node.childrenAreaHeight / 2 + let totalTop = top + marginY + node.children.forEach(cur => { + cur.top = totalTop + totalTop += cur.height + marginY + }) } - let { - left, - top, - width, - height, - expandBtnSize - } = node - node.children.forEach((item, index) => { - let x1 = node.layerIndex === 0 ? left + width / 2 : left + width + expandBtnSize - let y1 = top + height / 2 - let x2 = item.left - let y2 = item.top + item.height / 2 - let path = `M ${x1},${y1} L ${x2},${y2}` - lines[index].plot(path) - style && style(lines[index], item) - }) - } + }, + null, + true + ) + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2022-09-30 14:17:43 - * @Desc: 曲线风格连线 - */ - renderLineCurve(node, lines, style) { - if (node.children.length <= 0) { - return []; + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-08 10:04:05 + * @Desc: 调整节点top + */ + adjustTopValue() { + walk( + this.root, + null, + (node, parent, isRoot, layerIndex) => { + if (!node.nodeData.data.expand) { + return } - let { - left, - top, - width, - height, - expandBtnSize - } = node - node.children.forEach((item, index) => { - let x1 = node.layerIndex === 0 ? left + width / 2 : left + width + expandBtnSize - let y1 = top + height / 2 - let x2 = item.left - let y2 = item.top + item.height / 2 - let path = '' - if (node.isRoot) { - path = this.quadraticCurvePath(x1, y1, x2, y2) - } else { - path = this.cubicBezierPath(x1, y1, x2, y2) - } - lines[index].plot(path) - style && style(lines[index], item) - }) - } + // 判断子节点所占的高度之和是否大于该节点自身,大于则需要调整位置 + let difference = + node.childrenAreaHeight - + this.getMarginY(layerIndex + 1) * 2 - + node.height + if (difference > 0) { + this.updateBrothers(node, difference / 2) + } + }, + null, + true + ) + } - /** - * @Author: 王林 - * @Date: 2021-04-11 19:54:26 - * @Desc: 渲染按钮 - */ - renderExpandBtn(node, btn) { - let { - width, - height - } = node - let { - translateX, - translateY - } = btn.transform() - btn.translate(width - translateX, height / 2 - translateY) + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-07 14:26:03 + * @Desc: 更新兄弟节点的top + */ + updateBrothers(node, addHeight) { + if (node.parent) { + let childrenList = node.parent.children + let index = childrenList.findIndex(item => { + return item === node + }) + childrenList.forEach((item, _index) => { + if (item === node || item.hasCustomPosition()) { + // 适配自定义位置 + return + } + let _offset = 0 + // 上面的节点往上移 + if (_index < index) { + _offset = -addHeight + } else if (_index > index) { + // 下面的节点往下移 + _offset = addHeight + } + item.top += _offset + // 同步更新子节点的位置 + if (item.children && item.children.length) { + this.updateChildren(item.children, 'top', _offset) + } + }) + // 更新父节点的位置 + this.updateBrothers(node.parent, addHeight) } + } - /** - * @Author: 王林 - * @Date: 2022-07-30 08:30:35 - * @Desc: 创建概要节点 - */ - renderGeneralization(node, gLine, gNode) { - let { top, bottom, right, generalizationLineMargin, generalizationNodeMargin } = this.getNodeBoundaries(node, 'h') - let x1 = right + generalizationLineMargin - let y1 = top - let x2 = right + generalizationLineMargin - let y2 = bottom - let cx = x1 + 20 - let cy = y1 + (y2 - y1) / 2 - let path = `M ${x1},${y1} Q ${cx},${cy} ${x2},${y2}` - gLine.plot(path) - gNode.left = right + generalizationNodeMargin - gNode.top = top + (bottom - top - gNode.height) / 2 + /** + * @Author: 王林 + * @Date: 2021-04-11 14:42:48 + * @Desc: 绘制连线,连接该节点到其子节点 + */ + renderLine(node, lines, style, lineStyle) { + if (lineStyle === 'curve') { + this.renderLineCurve(node, lines, style) + } else if (lineStyle === 'direct') { + this.renderLineDirect(node, lines, style) + } else { + this.renderLineStraight(node, lines, style) } + } + + /** + * javascript comment + * @Author: 王林25 + * @Date: 2022-09-30 14:17:30 + * @Desc: 直线风格连线 + */ + renderLineStraight(node, lines, style) { + if (node.children.length <= 0) { + return [] + } + let { left, top, width, height, expandBtnSize } = node + let marginX = this.getMarginX(node.layerIndex + 1) + let s1 = (marginX - expandBtnSize) * 0.6 + node.children.forEach((item, index) => { + let x1 = + node.layerIndex === 0 ? left + width : left + width + expandBtnSize + let y1 = top + height / 2 + let x2 = item.left + let y2 = item.top + item.height / 2 + let path = `M ${x1},${y1} L ${x1 + s1},${y1} L ${ + x1 + s1 + },${y2} L ${x2},${y2}` + lines[index].plot(path) + style && style(lines[index], item) + }) + } + + /** + * javascript comment + * @Author: 王林25 + * @Date: 2022-09-30 14:34:41 + * @Desc: 直连风格 + */ + renderLineDirect(node, lines, style) { + if (node.children.length <= 0) { + return [] + } + let { left, top, width, height, expandBtnSize } = node + node.children.forEach((item, index) => { + let x1 = + node.layerIndex === 0 ? left + width / 2 : left + width + expandBtnSize + let y1 = top + height / 2 + let x2 = item.left + let y2 = item.top + item.height / 2 + let path = `M ${x1},${y1} L ${x2},${y2}` + lines[index].plot(path) + style && style(lines[index], item) + }) + } + + /** + * javascript comment + * @Author: 王林25 + * @Date: 2022-09-30 14:17:43 + * @Desc: 曲线风格连线 + */ + renderLineCurve(node, lines, style) { + if (node.children.length <= 0) { + return [] + } + let { left, top, width, height, expandBtnSize } = node + node.children.forEach((item, index) => { + let x1 = + node.layerIndex === 0 ? left + width / 2 : left + width + expandBtnSize + let y1 = top + height / 2 + let x2 = item.left + let y2 = item.top + item.height / 2 + let path = '' + if (node.isRoot) { + path = this.quadraticCurvePath(x1, y1, x2, y2) + } else { + path = this.cubicBezierPath(x1, y1, x2, y2) + } + lines[index].plot(path) + style && style(lines[index], item) + }) + } + + /** + * @Author: 王林 + * @Date: 2021-04-11 19:54:26 + * @Desc: 渲染按钮 + */ + renderExpandBtn(node, btn) { + let { width, height } = node + let { translateX, translateY } = btn.transform() + btn.translate(width - translateX, height / 2 - translateY) + } + + /** + * @Author: 王林 + * @Date: 2022-07-30 08:30:35 + * @Desc: 创建概要节点 + */ + renderGeneralization(node, gLine, gNode) { + let { + top, + bottom, + right, + generalizationLineMargin, + generalizationNodeMargin + } = this.getNodeBoundaries(node, 'h') + let x1 = right + generalizationLineMargin + let y1 = top + let x2 = right + generalizationLineMargin + let y2 = bottom + let cx = x1 + 20 + let cy = y1 + (y2 - y1) / 2 + let path = `M ${x1},${y1} Q ${cx},${cy} ${x2},${y2}` + gLine.plot(path) + gNode.left = right + generalizationNodeMargin + gNode.top = top + (bottom - top - gNode.height) / 2 + } } -export default LogicalStructure \ No newline at end of file +export default LogicalStructure diff --git a/simple-mind-map/src/layouts/MindMap.js b/simple-mind-map/src/layouts/MindMap.js index 75cc6cce..a338c644 100644 --- a/simple-mind-map/src/layouts/MindMap.js +++ b/simple-mind-map/src/layouts/MindMap.js @@ -1,336 +1,372 @@ -import Base from './Base'; -import { - walk, - asyncRun -} from '../utils' +import Base from './Base' +import { walk, asyncRun } from '../utils' -/** - * @Author: 王林 - * @Date: 2021-04-12 22:25:58 - * @Desc: 思维导图 +/** + * @Author: 王林 + * @Date: 2021-04-12 22:25:58 + * @Desc: 思维导图 * 在逻辑结构图的基础上增加一个变量来记录生长方向,向左还是向右,同时在计算left的时候根据方向来计算、调整top时只考虑同方向的节点即可 */ class MindMap extends Base { - /** - * @Author: 王林 - * @Date: 2021-04-12 22:26:31 - * @Desc: 构造函数 - */ - constructor(opt = {}) { - super(opt) - } + /** + * @Author: 王林 + * @Date: 2021-04-12 22:26:31 + * @Desc: 构造函数 + */ + constructor(opt = {}) { + super(opt) + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-06 14:04:20 - * @Desc: 布局 - */ - doLayout(callback) { - let task = [() => { - this.computedBaseValue() - }, () => { - this.computedTopValue() - }, () => { - this.adjustTopValue() - }, () => { - callback(this.root) - }] - asyncRun(task) - } + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-06 14:04:20 + * @Desc: 布局 + */ + doLayout(callback) { + let task = [ + () => { + this.computedBaseValue() + }, + () => { + this.computedTopValue() + }, + () => { + this.adjustTopValue() + }, + () => { + callback(this.root) + } + ] + asyncRun(task) + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-08 09:49:32 - * @Desc: 遍历数据计算节点的left、width、height - */ - computedBaseValue() { - walk(this.renderer.renderTree, null, (cur, parent, isRoot, layerIndex, index) => { - let newNode = this.createNode(cur, parent, isRoot, layerIndex) - // 根节点定位在画布中心位置 - if (isRoot) { - this.setNodeCenter(newNode) - } else { - // 非根节点 - // 三级及以下节点以上级为准 - if (parent._node.dir) { - newNode.dir = parent._node.dir - } else { // 节点生长方向 - newNode.dir = index % 2 === 0 ? 'right' : 'left' - } - // 根据生长方向定位到父节点的左侧或右侧 - newNode.left = newNode.dir === 'right' ? parent._node.left + parent._node.width + this.getMarginX(layerIndex) : parent._node.left - this.getMarginX(layerIndex) - newNode.width - } - if (!cur.data.expand) { - return true; - } - }, (cur, parent, isRoot, layerIndex) => { - // 返回时计算节点的leftChildrenAreaHeight和rightChildrenAreaHeight,也就是左侧和右侧子节点所占的高度之和,包括外边距 - if (!cur.data.expand) { - cur._node.leftChildrenAreaHeight = 0 - cur._node.rightChildrenAreaHeight = 0 - return - } - // 理论上只有根节点是存在两个方向的子节点的,其他节点的子节点一定全都是同方向,但是为了逻辑统一,就不按特殊处理的方式来写了 - let leftLen = 0 - let rightLen = 0 - let leftChildrenAreaHeight = 0 - let rightChildrenAreaHeight = 0 - cur._node.children.forEach((item) => { - if (item.dir === 'left') { - leftLen++ - leftChildrenAreaHeight += item.height - } else { - rightLen++ - rightChildrenAreaHeight += item.height - } - }) - cur._node.leftChildrenAreaHeight = leftChildrenAreaHeight + (leftLen + 1) * this.getMarginY(layerIndex + 1) - cur._node.rightChildrenAreaHeight = rightChildrenAreaHeight + (rightLen + 1) * this.getMarginY(layerIndex + 1) - }, true, 0) - } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-08 09:59:25 - * @Desc: 遍历节点树计算节点的top - */ - computedTopValue() { - walk(this.root, null, (node, parent, isRoot, layerIndex) => { - if (node.nodeData.data.expand && node.children && node.children.length) { - let marginY = this.getMarginY(layerIndex + 1) - let baseTop = node.top + node.height / 2 + marginY - // 第一个子节点的top值 = 该节点中心的top值 - 子节点的高度之和的一半 - let leftTotalTop = baseTop - node.leftChildrenAreaHeight / 2 - let rightTotalTop = baseTop - node.rightChildrenAreaHeight / 2 - node.children.forEach((cur) => { - if (cur.dir === 'left') { - cur.top = leftTotalTop - leftTotalTop += cur.height + marginY - } else { - cur.top = rightTotalTop - rightTotalTop += cur.height + marginY - } - }) - } - }, null, true) - } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-08 10:04:05 - * @Desc: 调整节点top - */ - adjustTopValue() { - walk(this.root, null, (node, parent, isRoot, layerIndex) => { - if (!node.nodeData.data.expand) { - return; - } - // 判断子节点所占的高度之和是否大于该节点自身,大于则需要调整位置 - let base = this.getMarginY(layerIndex + 1) * 2 + node.height - let leftDifference = node.leftChildrenAreaHeight - base - let rightDifference = node.rightChildrenAreaHeight - base - if (leftDifference > 0 || rightDifference > 0) { - this.updateBrothers(node, leftDifference / 2, rightDifference / 2) - } - }, null, true) - } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-07 14:26:03 - * @Desc: 更新兄弟节点的top - */ - updateBrothers(node, leftAddHeight, rightAddHeight) { - if (node.parent) { - // 过滤出和自己同方向的节点 - let childrenList = node.parent.children.filter((item) => { - return item.dir === node.dir - }) - let index = childrenList.findIndex((item) => { - return item === node - }) - childrenList.forEach((item, _index) => { - if (item.hasCustomPosition()) {// 适配自定义位置 - return - } - let _offset = 0 - let addHeight = item.dir === 'left' ? leftAddHeight : rightAddHeight - // 上面的节点往上移 - if (_index < index) { - _offset = -addHeight - } else if (_index > index) { // 下面的节点往下移 - _offset = addHeight - } - item.top += _offset - // 同步更新子节点的位置 - if (item.children && item.children.length) { - this.updateChildren(item.children, 'top', _offset) - } - }) - // 更新父节点的位置 - this.updateBrothers(node.parent, leftAddHeight, rightAddHeight) - } - } - - /** - * @Author: 王林 - * @Date: 2021-04-11 14:42:48 - * @Desc: 绘制连线,连接该节点到其子节点 - */ - renderLine(node, lines, style, lineStyle) { - if (lineStyle === 'curve') { - this.renderLineCurve(node, lines, style) - } else if (lineStyle === 'direct') { - this.renderLineDirect(node, lines, style) + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-08 09:49:32 + * @Desc: 遍历数据计算节点的left、width、height + */ + computedBaseValue() { + walk( + this.renderer.renderTree, + null, + (cur, parent, isRoot, layerIndex, index) => { + let newNode = this.createNode(cur, parent, isRoot, layerIndex) + // 根节点定位在画布中心位置 + if (isRoot) { + this.setNodeCenter(newNode) } else { - this.renderLineStraight(node, lines, style) + // 非根节点 + // 三级及以下节点以上级为准 + if (parent._node.dir) { + newNode.dir = parent._node.dir + } else { + // 节点生长方向 + newNode.dir = index % 2 === 0 ? 'right' : 'left' + } + // 根据生长方向定位到父节点的左侧或右侧 + newNode.left = + newNode.dir === 'right' + ? parent._node.left + + parent._node.width + + this.getMarginX(layerIndex) + : parent._node.left - this.getMarginX(layerIndex) - newNode.width } - } + if (!cur.data.expand) { + return true + } + }, + (cur, parent, isRoot, layerIndex) => { + // 返回时计算节点的leftChildrenAreaHeight和rightChildrenAreaHeight,也就是左侧和右侧子节点所占的高度之和,包括外边距 + if (!cur.data.expand) { + cur._node.leftChildrenAreaHeight = 0 + cur._node.rightChildrenAreaHeight = 0 + return + } + // 理论上只有根节点是存在两个方向的子节点的,其他节点的子节点一定全都是同方向,但是为了逻辑统一,就不按特殊处理的方式来写了 + let leftLen = 0 + let rightLen = 0 + let leftChildrenAreaHeight = 0 + let rightChildrenAreaHeight = 0 + cur._node.children.forEach(item => { + if (item.dir === 'left') { + leftLen++ + leftChildrenAreaHeight += item.height + } else { + rightLen++ + rightChildrenAreaHeight += item.height + } + }) + cur._node.leftChildrenAreaHeight = + leftChildrenAreaHeight + + (leftLen + 1) * this.getMarginY(layerIndex + 1) + cur._node.rightChildrenAreaHeight = + rightChildrenAreaHeight + + (rightLen + 1) * this.getMarginY(layerIndex + 1) + }, + true, + 0 + ) + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2022-09-30 14:10:47 - * @Desc: 直线风格连线 - */ - renderLineStraight(node, lines, style) { - if (node.children.length <= 0) { - return []; - } - let { - left, - top, - width, - height, - expandBtnSize - } = node - let marginX = this.getMarginX(node.layerIndex + 1) - let s1 = (marginX - expandBtnSize) * 0.6 - node.children.forEach((item, index) => { - let x1 = 0 - let _s = 0 - if (item.dir === 'left') { - _s = -s1 - x1 = node.layerIndex === 0 ? left : left - expandBtnSize + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-08 09:59:25 + * @Desc: 遍历节点树计算节点的top + */ + computedTopValue() { + walk( + this.root, + null, + (node, parent, isRoot, layerIndex) => { + if ( + node.nodeData.data.expand && + node.children && + node.children.length + ) { + let marginY = this.getMarginY(layerIndex + 1) + let baseTop = node.top + node.height / 2 + marginY + // 第一个子节点的top值 = 该节点中心的top值 - 子节点的高度之和的一半 + let leftTotalTop = baseTop - node.leftChildrenAreaHeight / 2 + let rightTotalTop = baseTop - node.rightChildrenAreaHeight / 2 + node.children.forEach(cur => { + if (cur.dir === 'left') { + cur.top = leftTotalTop + leftTotalTop += cur.height + marginY } else { - _s = s1 - x1 = node.layerIndex === 0 ? left + width : left + width + expandBtnSize + cur.top = rightTotalTop + rightTotalTop += cur.height + marginY } - let y1 = top + height / 2 - let x2 = item.dir === 'left' ? item.left + item.width : item.left - let y2 = item.top + item.height / 2 - let path = `M ${x1},${y1} L ${x1 + _s},${y1} L ${x1 + _s},${y2} L ${x2},${y2}` - lines[index].plot(path) - style && style(lines[index], item) - }) - } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2022-09-30 14:34:41 - * @Desc: 直连风格 - */ - renderLineDirect(node, lines, style) { - if (node.children.length <= 0) { - return []; + }) } - let { - left, - top, - width, - height, - expandBtnSize - } = node - node.children.forEach((item, index) => { - let x1 = node.layerIndex === 0 ? left + width / 2 : item.dir === 'left' ? left - expandBtnSize : left + width + expandBtnSize - let y1 = top + height / 2 - let x2 = item.dir === 'left' ? item.left + item.width : item.left - let y2 = item.top + item.height / 2 - let path = `M ${x1},${y1} L ${x2},${y2}` - lines[index].plot(path) - style && style(lines[index], item) - }) - } + }, + null, + true + ) + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2022-09-30 14:10:56 - * @Desc: 曲线风格连线 - */ - renderLineCurve(node, lines, style) { - if (node.children.length <= 0) { - return []; + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-08 10:04:05 + * @Desc: 调整节点top + */ + adjustTopValue() { + walk( + this.root, + null, + (node, parent, isRoot, layerIndex) => { + if (!node.nodeData.data.expand) { + return } - let { - left, - top, - width, - height, - expandBtnSize - } = node - node.children.forEach((item, index) => { - let x1 = node.layerIndex === 0 ? left + width / 2 : item.dir === 'left' ? left - expandBtnSize : left + width + 20 - let y1 = top + height / 2 - let x2 = item.dir === 'left' ? item.left + item.width : item.left - let y2 = item.top + item.height / 2 - let path = '' - if (node.isRoot) { - path = this.quadraticCurvePath(x1, y1, x2, y2) - } else { - path = this.cubicBezierPath(x1, y1, x2, y2) - } - lines[index].plot(path) - style && style(lines[index], item) - }) - } + // 判断子节点所占的高度之和是否大于该节点自身,大于则需要调整位置 + let base = this.getMarginY(layerIndex + 1) * 2 + node.height + let leftDifference = node.leftChildrenAreaHeight - base + let rightDifference = node.rightChildrenAreaHeight - base + if (leftDifference > 0 || rightDifference > 0) { + this.updateBrothers(node, leftDifference / 2, rightDifference / 2) + } + }, + null, + true + ) + } - /** - * @Author: 王林 - * @Date: 2021-04-11 19:54:26 - * @Desc: 渲染按钮 - */ - renderExpandBtn(node, btn) { - let { - width, - height, - expandBtnSize - } = node - let { - translateX, - translateY - } = btn.transform() - let x = (node.dir === 'left' ? 0 - expandBtnSize : width) - translateX - let y = height / 2 - translateY - btn.translate(x, y) + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-07 14:26:03 + * @Desc: 更新兄弟节点的top + */ + updateBrothers(node, leftAddHeight, rightAddHeight) { + if (node.parent) { + // 过滤出和自己同方向的节点 + let childrenList = node.parent.children.filter(item => { + return item.dir === node.dir + }) + let index = childrenList.findIndex(item => { + return item === node + }) + childrenList.forEach((item, _index) => { + if (item.hasCustomPosition()) { + // 适配自定义位置 + return + } + let _offset = 0 + let addHeight = item.dir === 'left' ? leftAddHeight : rightAddHeight + // 上面的节点往上移 + if (_index < index) { + _offset = -addHeight + } else if (_index > index) { + // 下面的节点往下移 + _offset = addHeight + } + item.top += _offset + // 同步更新子节点的位置 + if (item.children && item.children.length) { + this.updateChildren(item.children, 'top', _offset) + } + }) + // 更新父节点的位置 + this.updateBrothers(node.parent, leftAddHeight, rightAddHeight) } + } - /** - * @Author: 王林 - * @Date: 2022-07-30 08:30:35 - * @Desc: 创建概要节点 - */ - renderGeneralization(node, gLine, gNode) { - let isLeft = node.dir === 'left' - let { top, bottom, left, right, generalizationLineMargin, generalizationNodeMargin } = this.getNodeBoundaries(node, 'h', isLeft) - let x = isLeft ? left - generalizationLineMargin : right + generalizationLineMargin - let x1 = x - let y1 = top - let x2 = x - let y2 = bottom - let cx = x1 + (isLeft ? -20 : 20) - let cy = y1 + (y2 - y1) / 2 - let path = `M ${x1},${y1} Q ${cx},${cy} ${x2},${y2}` - gLine.plot(path) - gNode.left = x + (isLeft ? -generalizationNodeMargin : generalizationNodeMargin) - (isLeft ? gNode.width : 0) - gNode.top = top + (bottom - top - gNode.height) / 2 + /** + * @Author: 王林 + * @Date: 2021-04-11 14:42:48 + * @Desc: 绘制连线,连接该节点到其子节点 + */ + renderLine(node, lines, style, lineStyle) { + if (lineStyle === 'curve') { + this.renderLineCurve(node, lines, style) + } else if (lineStyle === 'direct') { + this.renderLineDirect(node, lines, style) + } else { + this.renderLineStraight(node, lines, style) } + } + + /** + * javascript comment + * @Author: 王林25 + * @Date: 2022-09-30 14:10:47 + * @Desc: 直线风格连线 + */ + renderLineStraight(node, lines, style) { + if (node.children.length <= 0) { + return [] + } + let { left, top, width, height, expandBtnSize } = node + let marginX = this.getMarginX(node.layerIndex + 1) + let s1 = (marginX - expandBtnSize) * 0.6 + node.children.forEach((item, index) => { + let x1 = 0 + let _s = 0 + if (item.dir === 'left') { + _s = -s1 + x1 = node.layerIndex === 0 ? left : left - expandBtnSize + } else { + _s = s1 + x1 = node.layerIndex === 0 ? left + width : left + width + expandBtnSize + } + let y1 = top + height / 2 + let x2 = item.dir === 'left' ? item.left + item.width : item.left + let y2 = item.top + item.height / 2 + let path = `M ${x1},${y1} L ${x1 + _s},${y1} L ${ + x1 + _s + },${y2} L ${x2},${y2}` + lines[index].plot(path) + style && style(lines[index], item) + }) + } + + /** + * javascript comment + * @Author: 王林25 + * @Date: 2022-09-30 14:34:41 + * @Desc: 直连风格 + */ + renderLineDirect(node, lines, style) { + if (node.children.length <= 0) { + return [] + } + let { left, top, width, height, expandBtnSize } = node + node.children.forEach((item, index) => { + let x1 = + node.layerIndex === 0 + ? left + width / 2 + : item.dir === 'left' + ? left - expandBtnSize + : left + width + expandBtnSize + let y1 = top + height / 2 + let x2 = item.dir === 'left' ? item.left + item.width : item.left + let y2 = item.top + item.height / 2 + let path = `M ${x1},${y1} L ${x2},${y2}` + lines[index].plot(path) + style && style(lines[index], item) + }) + } + + /** + * javascript comment + * @Author: 王林25 + * @Date: 2022-09-30 14:10:56 + * @Desc: 曲线风格连线 + */ + renderLineCurve(node, lines, style) { + if (node.children.length <= 0) { + return [] + } + let { left, top, width, height, expandBtnSize } = node + node.children.forEach((item, index) => { + let x1 = + node.layerIndex === 0 + ? left + width / 2 + : item.dir === 'left' + ? left - expandBtnSize + : left + width + 20 + let y1 = top + height / 2 + let x2 = item.dir === 'left' ? item.left + item.width : item.left + let y2 = item.top + item.height / 2 + let path = '' + if (node.isRoot) { + path = this.quadraticCurvePath(x1, y1, x2, y2) + } else { + path = this.cubicBezierPath(x1, y1, x2, y2) + } + lines[index].plot(path) + style && style(lines[index], item) + }) + } + + /** + * @Author: 王林 + * @Date: 2021-04-11 19:54:26 + * @Desc: 渲染按钮 + */ + renderExpandBtn(node, btn) { + let { width, height, expandBtnSize } = node + let { translateX, translateY } = btn.transform() + let x = (node.dir === 'left' ? 0 - expandBtnSize : width) - translateX + let y = height / 2 - translateY + btn.translate(x, y) + } + + /** + * @Author: 王林 + * @Date: 2022-07-30 08:30:35 + * @Desc: 创建概要节点 + */ + renderGeneralization(node, gLine, gNode) { + let isLeft = node.dir === 'left' + let { + top, + bottom, + left, + right, + generalizationLineMargin, + generalizationNodeMargin + } = this.getNodeBoundaries(node, 'h', isLeft) + let x = isLeft + ? left - generalizationLineMargin + : right + generalizationLineMargin + let x1 = x + let y1 = top + let x2 = x + let y2 = bottom + let cx = x1 + (isLeft ? -20 : 20) + let cy = y1 + (y2 - y1) / 2 + let path = `M ${x1},${y1} Q ${cx},${cy} ${x2},${y2}` + gLine.plot(path) + gNode.left = + x + + (isLeft ? -generalizationNodeMargin : generalizationNodeMargin) - + (isLeft ? gNode.width : 0) + gNode.top = top + (bottom - top - gNode.height) / 2 + } } -export default MindMap \ No newline at end of file +export default MindMap diff --git a/simple-mind-map/src/layouts/OrganizationStructure.js b/simple-mind-map/src/layouts/OrganizationStructure.js index a2795d7e..4e405dd5 100644 --- a/simple-mind-map/src/layouts/OrganizationStructure.js +++ b/simple-mind-map/src/layouts/OrganizationStructure.js @@ -1,280 +1,304 @@ -import Base from './Base'; -import { - walk, - asyncRun -} from '../utils' +import Base from './Base' +import { walk, asyncRun } from '../utils' -/** - * @Author: 王林 - * @Date: 2021-04-12 22:25:58 +/** + * @Author: 王林 + * @Date: 2021-04-12 22:25:58 * @Desc: 组织结构图 * 和逻辑结构图基本一样,只是方向变成向下生长,所以先计算节点的top,后计算节点的left、最后调整节点的left即可 */ class OrganizationStructure extends Base { - /** - * @Author: 王林 - * @Date: 2021-04-12 22:26:31 - * @Desc: 构造函数 - */ - constructor(opt = {}) { - super(opt) - } + /** + * @Author: 王林 + * @Date: 2021-04-12 22:26:31 + * @Desc: 构造函数 + */ + constructor(opt = {}) { + super(opt) + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-06 14:04:20 - * @Desc: 布局 - */ - doLayout(callback) { - let task = [() => { - this.computedBaseValue() - }, () => { - this.computedLeftValue() - }, () => { - this.adjustLeftValue() - }, () => { - callback(this.root) - }] - asyncRun(task) - } + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-06 14:04:20 + * @Desc: 布局 + */ + doLayout(callback) { + let task = [ + () => { + this.computedBaseValue() + }, + () => { + this.computedLeftValue() + }, + () => { + this.adjustLeftValue() + }, + () => { + callback(this.root) + } + ] + asyncRun(task) + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-08 09:49:32 - * @Desc: 遍历数据计算节点的left、width、height - */ - computedBaseValue() { - walk(this.renderer.renderTree, null, (cur, parent, isRoot, layerIndex) => { - let newNode = this.createNode(cur, parent, isRoot, layerIndex) - // 根节点定位在画布中心位置 - if (isRoot) { - this.setNodeCenter(newNode) - } else { - // 非根节点 - // 定位到父节点下方 - newNode.top = parent._node.top + parent._node.height + this.getMarginX(layerIndex) - } - if (!cur.data.expand) { - return true; - } - }, (cur, parent, isRoot, layerIndex) => { - // 返回时计算节点的areaWidth,也就是子节点所占的宽度之和,包括外边距 - let len = cur.data.expand === false ? 0 : cur._node.children.length - cur._node.childrenAreaWidth = len ? cur._node.children.reduce((h, item) => { - return h + item.width - }, 0) + (len + 1) * this.getMarginY(layerIndex + 1) : 0 - }, true, 0) - } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-08 09:59:25 - * @Desc: 遍历节点树计算节点的left - */ - computedLeftValue() { - walk(this.root, null, (node, parent, isRoot, layerIndex) => { - if (node.nodeData.data.expand && node.children && node.children.length) { - let marginX = this.getMarginY(layerIndex + 1) - // 第一个子节点的left值 = 该节点中心的left值 - 子节点的宽度之和的一半 - let left = node.left + node.width / 2 - node.childrenAreaWidth / 2 - let totalLeft = left + marginX - node.children.forEach((cur) => { - cur.left = totalLeft - totalLeft += cur.width + marginX - }) - } - }, null, true) - } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-08 10:04:05 - * @Desc: 调整节点left - */ - adjustLeftValue() { - walk(this.root, null, (node, parent, isRoot, layerIndex) => { - if (!node.nodeData.data.expand) { - return; - } - // 判断子节点所占的宽度之和是否大于该节点自身,大于则需要调整位置 - let difference = node.childrenAreaWidth - this.getMarginY(layerIndex + 1) * 2 - node.width - if (difference > 0) { - this.updateBrothers(node, difference / 2) - } - }, null, true) - } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-07 14:26:03 - * @Desc: 更新兄弟节点的left - */ - updateBrothers(node, addWidth) { - if (node.parent) { - let childrenList = node.parent.children - let index = childrenList.findIndex((item) => { - return item === node - }) - childrenList.forEach((item, _index) => { - if (item.hasCustomPosition()) {// 适配自定义位置 - return - } - let _offset = 0 - // 上面的节点往上移 - if (_index < index) { - _offset = -addWidth - } else if (_index > index) { // 下面的节点往下移 - _offset = addWidth - } - item.left += _offset - // 同步更新子节点的位置 - if (item.children && item.children.length) { - this.updateChildren(item.children, 'left', _offset) - } - }) - // 更新父节点的位置 - this.updateBrothers(node.parent, addWidth) - } - } - - /** - * @Author: 王林 - * @Date: 2021-04-11 14:42:48 - * @Desc: 绘制连线,连接该节点到其子节点 - */ - renderLine(node, lines, style, lineStyle) { - if (lineStyle === 'direct') { - this.renderLineDirect(node, lines, style) + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-08 09:49:32 + * @Desc: 遍历数据计算节点的left、width、height + */ + computedBaseValue() { + walk( + this.renderer.renderTree, + null, + (cur, parent, isRoot, layerIndex) => { + let newNode = this.createNode(cur, parent, isRoot, layerIndex) + // 根节点定位在画布中心位置 + if (isRoot) { + this.setNodeCenter(newNode) } else { - this.renderLineStraight(node, lines, style) + // 非根节点 + // 定位到父节点下方 + newNode.top = + parent._node.top + parent._node.height + this.getMarginX(layerIndex) } - } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2022-09-30 14:34:41 - * @Desc: 直连风格 - */ - renderLineDirect(node, lines, style) { - if (node.children.length <= 0) { - return []; + if (!cur.data.expand) { + return true } - let { - left, - top, - width, - height, - } = node - let x1 = left + width / 2 - let y1 = top + height - node.children.forEach((item, index) => { - let x2 = item.left + item.width / 2 - let y2 = item.top - let path = `M ${x1},${y1} L ${x2},${y2}` - lines[index].plot(path) - style && style(lines[index], item) - }) - } + }, + (cur, parent, isRoot, layerIndex) => { + // 返回时计算节点的areaWidth,也就是子节点所占的宽度之和,包括外边距 + let len = cur.data.expand === false ? 0 : cur._node.children.length + cur._node.childrenAreaWidth = len + ? cur._node.children.reduce((h, item) => { + return h + item.width + }, 0) + + (len + 1) * this.getMarginY(layerIndex + 1) + : 0 + }, + true, + 0 + ) + } - /** - * javascript comment - * @Author: 王林25 - * @Date: 2022-09-30 14:39:07 - * @Desc: 直线风格连线 - */ - renderLineStraight(node, lines, style) { - if (node.children.length <= 0) { - return []; + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-08 09:59:25 + * @Desc: 遍历节点树计算节点的left + */ + computedLeftValue() { + walk( + this.root, + null, + (node, parent, isRoot, layerIndex) => { + if ( + node.nodeData.data.expand && + node.children && + node.children.length + ) { + let marginX = this.getMarginY(layerIndex + 1) + // 第一个子节点的left值 = 该节点中心的left值 - 子节点的宽度之和的一半 + let left = node.left + node.width / 2 - node.childrenAreaWidth / 2 + let totalLeft = left + marginX + node.children.forEach(cur => { + cur.left = totalLeft + totalLeft += cur.width + marginX + }) } - let { - left, - top, - width, - height, - expandBtnSize, - isRoot - } = node - let x1 = left + width / 2 - let y1 = top + height - let marginX = this.getMarginX(node.layerIndex + 1) - let s1 = marginX * 0.7 - let minx = Infinity - let maxx = -Infinity - let len = node.children.length - node.children.forEach((item, index) => { - let x2 = item.left + item.width / 2 - let y2 = y1 + s1 > item.top ? item.top + item.height : item.top - if (x2 < minx) { - minx = x2 - } - if (x2 > maxx) { - maxx = x2 - } - let path = `M ${x2},${y1 + s1} L ${x2},${y2}` - lines[index].plot(path) - style && style(lines[index], item) - }) - minx = Math.min(x1, minx) - maxx = Math.max(x1, maxx) - // 父节点的竖线 - let line1 = this.draw.path() - node.style.line(line1) - expandBtnSize = len > 0 && !isRoot ? expandBtnSize : 0 - line1.plot(`M ${x1},${y1 + expandBtnSize} L ${x1},${y1 + s1}`) - node._lines.push(line1) - style && style(line1, node) - // 水平线 - if (len > 0) { - let lin2 = this.draw.path() - node.style.line(lin2) - lin2.plot(`M ${minx},${y1 + s1} L ${maxx},${y1 + s1}`) - node._lines.push(lin2) - style && style(lin2, node) + }, + null, + true + ) + } + + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-08 10:04:05 + * @Desc: 调整节点left + */ + adjustLeftValue() { + walk( + this.root, + null, + (node, parent, isRoot, layerIndex) => { + if (!node.nodeData.data.expand) { + return } - } + // 判断子节点所占的宽度之和是否大于该节点自身,大于则需要调整位置 + let difference = + node.childrenAreaWidth - + this.getMarginY(layerIndex + 1) * 2 - + node.width + if (difference > 0) { + this.updateBrothers(node, difference / 2) + } + }, + null, + true + ) + } - /** - * @Author: 王林 - * @Date: 2021-04-11 19:54:26 - * @Desc: 渲染按钮 - */ - renderExpandBtn(node, btn) { - let { - width, - height, - expandBtnSize - } = node - let { - translateX, - translateY - } = btn.transform() - btn.translate(width / 2 - expandBtnSize / 2 - translateX, height + expandBtnSize / 2 - translateY) + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-07 14:26:03 + * @Desc: 更新兄弟节点的left + */ + updateBrothers(node, addWidth) { + if (node.parent) { + let childrenList = node.parent.children + let index = childrenList.findIndex(item => { + return item === node + }) + childrenList.forEach((item, _index) => { + if (item.hasCustomPosition()) { + // 适配自定义位置 + return + } + let _offset = 0 + // 上面的节点往上移 + if (_index < index) { + _offset = -addWidth + } else if (_index > index) { + // 下面的节点往下移 + _offset = addWidth + } + item.left += _offset + // 同步更新子节点的位置 + if (item.children && item.children.length) { + this.updateChildren(item.children, 'left', _offset) + } + }) + // 更新父节点的位置 + this.updateBrothers(node.parent, addWidth) } + } - /** - * @Author: 王林 - * @Date: 2022-07-30 08:30:35 - * @Desc: 创建概要节点 - */ - renderGeneralization(node, gLine, gNode) { - let { bottom, left, right, generalizationLineMargin, generalizationNodeMargin } = this.getNodeBoundaries(node, 'v') - let x1 = left - let y1 = bottom + generalizationLineMargin - let x2 = right - let y2 = bottom + generalizationLineMargin - let cx = x1 + (x2 - x1) / 2 - let cy = y1 + 20 - let path = `M ${x1},${y1} Q ${cx},${cy} ${x2},${y2}` - gLine.plot(path) - gNode.top = bottom + generalizationNodeMargin - gNode.left = left + (right - left - gNode.width) / 2 + /** + * @Author: 王林 + * @Date: 2021-04-11 14:42:48 + * @Desc: 绘制连线,连接该节点到其子节点 + */ + renderLine(node, lines, style, lineStyle) { + if (lineStyle === 'direct') { + this.renderLineDirect(node, lines, style) + } else { + this.renderLineStraight(node, lines, style) } + } + + /** + * javascript comment + * @Author: 王林25 + * @Date: 2022-09-30 14:34:41 + * @Desc: 直连风格 + */ + renderLineDirect(node, lines, style) { + if (node.children.length <= 0) { + return [] + } + let { left, top, width, height } = node + let x1 = left + width / 2 + let y1 = top + height + node.children.forEach((item, index) => { + let x2 = item.left + item.width / 2 + let y2 = item.top + let path = `M ${x1},${y1} L ${x2},${y2}` + lines[index].plot(path) + style && style(lines[index], item) + }) + } + + /** + * javascript comment + * @Author: 王林25 + * @Date: 2022-09-30 14:39:07 + * @Desc: 直线风格连线 + */ + renderLineStraight(node, lines, style) { + if (node.children.length <= 0) { + return [] + } + let { left, top, width, height, expandBtnSize, isRoot } = node + let x1 = left + width / 2 + let y1 = top + height + let marginX = this.getMarginX(node.layerIndex + 1) + let s1 = marginX * 0.7 + let minx = Infinity + let maxx = -Infinity + let len = node.children.length + node.children.forEach((item, index) => { + let x2 = item.left + item.width / 2 + let y2 = y1 + s1 > item.top ? item.top + item.height : item.top + if (x2 < minx) { + minx = x2 + } + if (x2 > maxx) { + maxx = x2 + } + let path = `M ${x2},${y1 + s1} L ${x2},${y2}` + lines[index].plot(path) + style && style(lines[index], item) + }) + minx = Math.min(x1, minx) + maxx = Math.max(x1, maxx) + // 父节点的竖线 + let line1 = this.draw.path() + node.style.line(line1) + expandBtnSize = len > 0 && !isRoot ? expandBtnSize : 0 + line1.plot(`M ${x1},${y1 + expandBtnSize} L ${x1},${y1 + s1}`) + node._lines.push(line1) + style && style(line1, node) + // 水平线 + if (len > 0) { + let lin2 = this.draw.path() + node.style.line(lin2) + lin2.plot(`M ${minx},${y1 + s1} L ${maxx},${y1 + s1}`) + node._lines.push(lin2) + style && style(lin2, node) + } + } + + /** + * @Author: 王林 + * @Date: 2021-04-11 19:54:26 + * @Desc: 渲染按钮 + */ + renderExpandBtn(node, btn) { + let { width, height, expandBtnSize } = node + let { translateX, translateY } = btn.transform() + btn.translate( + width / 2 - expandBtnSize / 2 - translateX, + height + expandBtnSize / 2 - translateY + ) + } + + /** + * @Author: 王林 + * @Date: 2022-07-30 08:30:35 + * @Desc: 创建概要节点 + */ + renderGeneralization(node, gLine, gNode) { + let { + bottom, + left, + right, + generalizationLineMargin, + generalizationNodeMargin + } = this.getNodeBoundaries(node, 'v') + let x1 = left + let y1 = bottom + generalizationLineMargin + let x2 = right + let y2 = bottom + generalizationLineMargin + let cx = x1 + (x2 - x1) / 2 + let cy = y1 + 20 + let path = `M ${x1},${y1} Q ${cx},${cy} ${x2},${y2}` + gLine.plot(path) + gNode.top = bottom + generalizationNodeMargin + gNode.left = left + (right - left - gNode.width) / 2 + } } -export default OrganizationStructure \ No newline at end of file +export default OrganizationStructure diff --git a/simple-mind-map/src/parse/xmind.js b/simple-mind-map/src/parse/xmind.js index b6a18240..1199fdf9 100644 --- a/simple-mind-map/src/parse/xmind.js +++ b/simple-mind-map/src/parse/xmind.js @@ -1,5 +1,5 @@ -import JSZip from "jszip"; -import xmlConvert from "xml-js"; +import JSZip from 'jszip' +import xmlConvert from 'xml-js' /** * javascript comment @@ -7,35 +7,35 @@ import xmlConvert from "xml-js"; * @Date: 2022-09-21 14:07:47 * @Desc: 解析.xmind文件 */ -const parseXmindFile = (file) => { +const parseXmindFile = file => { return new Promise((resolve, reject) => { JSZip.loadAsync(file).then( - async (zip) => { + async zip => { try { - let content = ""; - if (zip.files["content.json"]) { - let json = await zip.files["content.json"].async("string"); - content = transformXmind(json); - } else if (zip.files["content.xml"]) { - let xml = await zip.files["content.xml"].async("string"); - let json = xmlConvert.xml2json(xml); - content = transformOldXmind(json); + let content = '' + if (zip.files['content.json']) { + let json = await zip.files['content.json'].async('string') + content = transformXmind(json) + } else if (zip.files['content.xml']) { + let xml = await zip.files['content.xml'].async('string') + let json = xmlConvert.xml2json(xml) + content = transformOldXmind(json) } if (content) { - resolve(content); + resolve(content) } else { - reject(new Error("解析失败")); + reject(new Error('解析失败')) } } catch (error) { - reject(error); + reject(error) } }, - (e) => { - reject(e); + e => { + reject(e) } - ); - }); -}; + ) + }) +} /** * javascript comment @@ -43,44 +43,44 @@ const parseXmindFile = (file) => { * @Date: 2022-09-21 18:57:25 * @Desc: 转换xmind数据 */ -const transformXmind = (content) => { - let data = JSON.parse(content)[0]; - let nodeTree = data.rootTopic; - let newTree = {}; +const transformXmind = content => { + let data = JSON.parse(content)[0] + let nodeTree = data.rootTopic + let newTree = {} let walk = (node, newNode) => { newNode.data = { // 节点内容 - text: node.title, - }; + text: node.title + } // 节点备注 if (node.notes) { - newNode.data.note = (node.notes.realHTML || node.notes.plain).content; + newNode.data.note = (node.notes.realHTML || node.notes.plain).content } // 超链接 if (node.href && /^https?:\/\//.test(node.href)) { - newNode.data.hyperlink = node.href; + newNode.data.hyperlink = node.href } // 标签 if (node.labels && node.labels.length > 0) { - newNode.data.tag = node.labels; + newNode.data.tag = node.labels } // 子节点 - newNode.children = []; + newNode.children = [] if ( node.children && node.children.attached && node.children.attached.length > 0 ) { - node.children.attached.forEach((item) => { - let newChild = {}; - newNode.children.push(newChild); - walk(item, newChild); - }); + node.children.attached.forEach(item => { + let newChild = {} + newNode.children.push(newChild) + walk(item, newChild) + }) } - }; - walk(nodeTree, newTree); - return newTree; -}; + } + walk(nodeTree, newTree) + return newTree +} /** * javascript comment @@ -88,86 +88,92 @@ const transformXmind = (content) => { * @Date: 2022-09-23 15:51:51 * @Desc: 转换旧版xmind数据,xmind8 */ -const transformOldXmind = (content) => { - let data = JSON.parse(content); - let elements = data.elements; - let root = null; - let getRoot = (arr) => { +const transformOldXmind = content => { + let data = JSON.parse(content) + let elements = data.elements + let root = null + let getRoot = arr => { for (let i = 0; i < arr.length; i++) { - if (!root && arr[i].name === "topic") { - root = arr[i]; - return; + if (!root && arr[i].name === 'topic') { + root = arr[i] + return } } - arr.forEach((item) => { - getRoot(item.elements); - }); - }; - getRoot(elements); - let newTree = {}; + arr.forEach(item => { + getRoot(item.elements) + }) + } + getRoot(elements) + let newTree = {} let getItemByName = (arr, name) => { - return arr.find((item) => { - return item.name === name; - }); - }; + return arr.find(item => { + return item.name === name + }) + } let walk = (node, newNode) => { - let nodeElements = node.elements; + let nodeElements = node.elements newNode.data = { // 节点内容 - text: getItemByName(nodeElements, "title").elements[0].text, - }; + text: getItemByName(nodeElements, 'title').elements[0].text + } try { // 节点备注 - let notesElement = getItemByName(nodeElements, "notes"); + let notesElement = getItemByName(nodeElements, 'notes') if (notesElement) { newNode.data.note = - notesElement.elements[0].elements[0].elements[0].text; + notesElement.elements[0].elements[0].elements[0].text } - } catch (error) {} + } catch (error) { + console.log(error) + } try { // 超链接 if ( node.attributes && - node.attributes["xlink:href"] && - /^https?:\/\//.test(node.attributes["xlink:href"]) + node.attributes['xlink:href'] && + /^https?:\/\//.test(node.attributes['xlink:href']) ) { - newNode.data.hyperlink = node.attributes["xlink:href"]; + newNode.data.hyperlink = node.attributes['xlink:href'] } - } catch (error) {} + } catch (error) { + console.log(error) + } try { // 标签 - let labelsElement = getItemByName(nodeElements, "labels"); + let labelsElement = getItemByName(nodeElements, 'labels') if (labelsElement) { - newNode.data.tag = labelsElement.elements.map((item) => { - return item.elements[0].text; - }); + newNode.data.tag = labelsElement.elements.map(item => { + return item.elements[0].text + }) } - } catch (error) {} - // 子节点 - newNode.children = []; - let _children = getItemByName(nodeElements, "children"); - if (_children && _children.elements && _children.elements.length > 0) { - _children.elements.forEach((item) => { - if (item.name === "topics") { - item.elements.forEach((item2) => { - let newChild = {}; - newNode.children.push(newChild); - walk(item2, newChild); - }); - } else { - let newChild = {}; - newNode.children.push(newChild); - walk(item, newChild); - } - }); + } catch (error) { + console.log(error) } - }; - walk(root, newTree); - return newTree; -}; + // 子节点 + newNode.children = [] + let _children = getItemByName(nodeElements, 'children') + if (_children && _children.elements && _children.elements.length > 0) { + _children.elements.forEach(item => { + if (item.name === 'topics') { + item.elements.forEach(item2 => { + let newChild = {} + newNode.children.push(newChild) + walk(item2, newChild) + }) + } else { + let newChild = {} + newNode.children.push(newChild) + walk(item, newChild) + } + }) + } + } + walk(root, newTree) + return newTree +} export default { parseXmindFile, transformXmind, - transformOldXmind, -}; + transformOldXmind +} diff --git a/simple-mind-map/src/svg/btns.js b/simple-mind-map/src/svg/btns.js index 06af683d..c099a4d9 100644 --- a/simple-mind-map/src/svg/btns.js +++ b/simple-mind-map/src/svg/btns.js @@ -1,18 +1,18 @@ -/** - * @Author: 王林 - * @Date: 2021-04-11 19:46:10 - * @Desc: 展开按钮 +/** + * @Author: 王林 + * @Date: 2021-04-11 19:46:10 + * @Desc: 展开按钮 */ const open = `` -/** - * @Author: 王林 - * @Date: 2021-04-11 19:46:23 - * @Desc: 收缩按钮 +/** + * @Author: 王林 + * @Date: 2021-04-11 19:46:23 + * @Desc: 收缩按钮 */ const close = `` export default { - open, - close -} \ No newline at end of file + open, + close +} diff --git a/simple-mind-map/src/svg/icons.js b/simple-mind-map/src/svg/icons.js index 58d4520c..ddb7ff8f 100644 --- a/simple-mind-map/src/svg/icons.js +++ b/simple-mind-map/src/svg/icons.js @@ -1,299 +1,301 @@ // 超链接图标 -const hyperlink = '' +const hyperlink = + '' // 备注图标 -const note = '' +const note = + '' // 节点icon export const nodeIconList = [ - { - name: '优先级图标', - type: 'priority', - list: [ - { - name: '1', - icon: `` - }, - { - name: '2', - icon: `` - }, - { - name: '3', - icon: `` - }, - { - name: '4', - icon: `` - }, - { - name: '5', - icon: `` - }, - { - name: '6', - icon: `` - }, - { - name: '7', - icon: `` - }, - { - name: '8', - icon: `` - }, - { - name: '9', - icon: `` - }, - { - name: '10', - icon: `` - } - ] - }, - { - name: '进度图标', - type: 'progress', - list: [ - { - name: '1', - icon: `` - }, - { - name: '2', - icon: `` - }, - { - name: '3', - icon: `` - }, - { - name: '4', - icon: `` - }, - { - name: '5', - icon: `` - }, - { - name: '6', - icon: `` - }, - { - name: '7', - icon: `` - }, - { - name: '8', - icon: `` - } - ] - }, - { - name: '表情图标', - type: 'expression', - list: [ - { - name: '1', - icon: `` - }, - { - name: '2', - icon: `` - }, - { - name: '3', - icon: `` - }, - { - name: '4', - icon: `` - }, - { - name: '5', - icon: `` - }, - { - name: '6', - icon: `` - }, - { - name: '7', - icon: `` - }, - { - name: '8', - icon: `` - }, - { - name: '9', - icon: `` - }, - { - name: '10', - icon: `` - }, - { - name: '11', - icon: `` - }, - { - name: '12', - icon: `` - }, - { - name: '13', - icon: `` - }, - { - name: '14', - icon: `` - }, - { - name: '15', - icon: `` - }, - { - name: '16', - icon: `` - }, - { - name: '17', - icon: `` - }, - { - name: '18', - icon: `` - }, - { - name: '19', - icon: `` - }, - { - name: '20', - icon: `` - } - ] - }, - { - name: '标记图标', - type: 'sign', - list: [ - { - name: '1', - icon: `` - }, - { - name: '2', - icon: `` - }, - { - name: '3', - icon: `` - }, - { - name: '4', - icon: `` - }, - { - name: '5', - icon: `` - }, - { - name: '6', - icon: `` - }, - { - name: '7', - icon: `` - }, - { - name: '8', - icon: `` - }, - { - name: '9', - icon: `` - }, - { - name: '10', - icon: `` - }, - { - name: '11', - icon: `` - }, - { - name: '12', - icon: `` - }, - { - name: '13', - icon: `` - }, - { - name: '14', - icon: `` - }, - { - name: '15', - icon: `` - }, - { - name: '16', - icon: `` - }, - { - name: '17', - icon: `` - }, - { - name: '18', - icon: `` - }, - { - name: '19', - icon: `` - }, - { - name: '20', - icon: `` - }, - { - name: '21', - icon: `` - }, - { - name: '22', - icon: `` - }, - { - name: '23', - icon: `` - } - ] - } + { + name: '优先级图标', + type: 'priority', + list: [ + { + name: '1', + icon: `` + }, + { + name: '2', + icon: `` + }, + { + name: '3', + icon: `` + }, + { + name: '4', + icon: `` + }, + { + name: '5', + icon: `` + }, + { + name: '6', + icon: `` + }, + { + name: '7', + icon: `` + }, + { + name: '8', + icon: `` + }, + { + name: '9', + icon: `` + }, + { + name: '10', + icon: `` + } + ] + }, + { + name: '进度图标', + type: 'progress', + list: [ + { + name: '1', + icon: `` + }, + { + name: '2', + icon: `` + }, + { + name: '3', + icon: `` + }, + { + name: '4', + icon: `` + }, + { + name: '5', + icon: `` + }, + { + name: '6', + icon: `` + }, + { + name: '7', + icon: `` + }, + { + name: '8', + icon: `` + } + ] + }, + { + name: '表情图标', + type: 'expression', + list: [ + { + name: '1', + icon: `` + }, + { + name: '2', + icon: `` + }, + { + name: '3', + icon: `` + }, + { + name: '4', + icon: `` + }, + { + name: '5', + icon: `` + }, + { + name: '6', + icon: `` + }, + { + name: '7', + icon: `` + }, + { + name: '8', + icon: `` + }, + { + name: '9', + icon: `` + }, + { + name: '10', + icon: `` + }, + { + name: '11', + icon: `` + }, + { + name: '12', + icon: `` + }, + { + name: '13', + icon: `` + }, + { + name: '14', + icon: `` + }, + { + name: '15', + icon: `` + }, + { + name: '16', + icon: `` + }, + { + name: '17', + icon: `` + }, + { + name: '18', + icon: `` + }, + { + name: '19', + icon: `` + }, + { + name: '20', + icon: `` + } + ] + }, + { + name: '标记图标', + type: 'sign', + list: [ + { + name: '1', + icon: `` + }, + { + name: '2', + icon: `` + }, + { + name: '3', + icon: `` + }, + { + name: '4', + icon: `` + }, + { + name: '5', + icon: `` + }, + { + name: '6', + icon: `` + }, + { + name: '7', + icon: `` + }, + { + name: '8', + icon: `` + }, + { + name: '9', + icon: `` + }, + { + name: '10', + icon: `` + }, + { + name: '11', + icon: `` + }, + { + name: '12', + icon: `` + }, + { + name: '13', + icon: `` + }, + { + name: '14', + icon: `` + }, + { + name: '15', + icon: `` + }, + { + name: '16', + icon: `` + }, + { + name: '17', + icon: `` + }, + { + name: '18', + icon: `` + }, + { + name: '19', + icon: `` + }, + { + name: '20', + icon: `` + }, + { + name: '21', + icon: `` + }, + { + name: '22', + icon: `` + }, + { + name: '23', + icon: `` + } + ] + } ] -/** - * @Author: 王林 - * @Date: 2021-06-23 22:36:56 - * @Desc: 获取nodeIconList icon内容 +/** + * @Author: 王林 + * @Date: 2021-06-23 22:36:56 + * @Desc: 获取nodeIconList icon内容 */ -const getNodeIconListIcon = (name) => { - let arr = name.split('_') - let typeData = nodeIconList.find((item) => { - return item.type === arr[0]; - }) - return typeData.list.find((item) => { - return item.name === arr[1] - }).icon; +const getNodeIconListIcon = name => { + let arr = name.split('_') + let typeData = nodeIconList.find(item => { + return item.type === arr[0] + }) + return typeData.list.find(item => { + return item.name === arr[1] + }).icon } export default { - hyperlink, - note, - nodeIconList, - getNodeIconListIcon -} \ No newline at end of file + hyperlink, + note, + nodeIconList, + getNodeIconListIcon +} diff --git a/simple-mind-map/src/themes/blueSky.js b/simple-mind-map/src/themes/blueSky.js index 87875d5d..aa085c28 100644 --- a/simple-mind-map/src/themes/blueSky.js +++ b/simple-mind-map/src/themes/blueSky.js @@ -1,53 +1,53 @@ -import defaultTheme from './default'; -import merge from 'deepmerge'; +import defaultTheme from './default' +import merge from 'deepmerge' -/** - * @Author: 王林 - * @Date: 2021-04-11 15:22:18 +/** + * @Author: 王林 + * @Date: 2021-04-11 15:22:18 * @Desc: 天空蓝 */ export default merge(defaultTheme, { - // 连线的颜色 - lineColor: 'rgb(115, 161, 191)', - // 背景颜色 - backgroundColor: 'rgb(251, 251, 251)', - // 概要连线的粗细 - generalizationLineWidth: 1, - // 概要连线的颜色 - generalizationLineColor: '#333', - // 根节点样式 - root: { - fillColor: 'rgb(115, 161, 191)', - active: { - borderColor: 'rgb(57, 80, 96)' - } - }, - // 二级节点样式 - second: { - fillColor: 'rgb(238, 243, 246)', - color: '#333', - borderColor: 'rgb(115, 161, 191)', - borderWidth: 1, - fontSize: 14, - active: { - borderColor: 'rgb(57, 80, 96)' - } - }, - // 三级及以下节点样式 - node: { - fontSize: 12, - color: '#333', - active: { - borderColor: 'rgb(57, 80, 96)' - } - }, - // 概要节点样式 - generalization: { - fillColor: '#fff', - borderColor: '#333', - color: '#333', - active: { - borderColor: 'rgb(57, 80, 96)' - } + // 连线的颜色 + lineColor: 'rgb(115, 161, 191)', + // 背景颜色 + backgroundColor: 'rgb(251, 251, 251)', + // 概要连线的粗细 + generalizationLineWidth: 1, + // 概要连线的颜色 + generalizationLineColor: '#333', + // 根节点样式 + root: { + fillColor: 'rgb(115, 161, 191)', + active: { + borderColor: 'rgb(57, 80, 96)' } -}) \ No newline at end of file + }, + // 二级节点样式 + second: { + fillColor: 'rgb(238, 243, 246)', + color: '#333', + borderColor: 'rgb(115, 161, 191)', + borderWidth: 1, + fontSize: 14, + active: { + borderColor: 'rgb(57, 80, 96)' + } + }, + // 三级及以下节点样式 + node: { + fontSize: 12, + color: '#333', + active: { + borderColor: 'rgb(57, 80, 96)' + } + }, + // 概要节点样式 + generalization: { + fillColor: '#fff', + borderColor: '#333', + color: '#333', + active: { + borderColor: 'rgb(57, 80, 96)' + } + } +}) diff --git a/simple-mind-map/src/themes/brainImpairedPink.js b/simple-mind-map/src/themes/brainImpairedPink.js index ecf8653f..a31881e2 100644 --- a/simple-mind-map/src/themes/brainImpairedPink.js +++ b/simple-mind-map/src/themes/brainImpairedPink.js @@ -1,53 +1,53 @@ -import defaultTheme from './default'; -import merge from 'deepmerge'; +import defaultTheme from './default' +import merge from 'deepmerge' -/** - * @Author: 王林 - * @Date: 2021-04-11 15:22:18 +/** + * @Author: 王林 + * @Date: 2021-04-11 15:22:18 * @Desc: 脑残粉 */ export default merge(defaultTheme, { - // 连线的颜色 - lineColor: 'rgb(191, 115, 148)', - // 背景颜色 - backgroundColor: 'rgb(251, 251, 251)', - // 概要连线的粗细 - generalizationLineWidth: 1, - // 概要连线的颜色 - generalizationLineColor: '#333', - // 根节点样式 - root: { - fillColor: 'rgb(191, 115, 148)', - active: { - borderColor: 'rgb(96, 57, 74)' - } - }, - // 二级节点样式 - second: { - fillColor: 'rgb(246, 238, 242)', - color: '#333', - borderColor: 'rgb(191, 115, 148)', - borderWidth: 1, - fontSize: 14, - active: { - borderColor: 'rgb(96, 57, 74)' - } - }, - // 三级及以下节点样式 - node: { - fontSize: 12, - color: '#333', - active: { - borderColor: 'rgb(96, 57, 74)' - } - }, - // 概要节点样式 - generalization: { - fillColor: '#fff', - borderColor: '#333', - color: '#333', - active: { - borderColor: 'rgb(96, 57, 74)' - } + // 连线的颜色 + lineColor: 'rgb(191, 115, 148)', + // 背景颜色 + backgroundColor: 'rgb(251, 251, 251)', + // 概要连线的粗细 + generalizationLineWidth: 1, + // 概要连线的颜色 + generalizationLineColor: '#333', + // 根节点样式 + root: { + fillColor: 'rgb(191, 115, 148)', + active: { + borderColor: 'rgb(96, 57, 74)' } -}) \ No newline at end of file + }, + // 二级节点样式 + second: { + fillColor: 'rgb(246, 238, 242)', + color: '#333', + borderColor: 'rgb(191, 115, 148)', + borderWidth: 1, + fontSize: 14, + active: { + borderColor: 'rgb(96, 57, 74)' + } + }, + // 三级及以下节点样式 + node: { + fontSize: 12, + color: '#333', + active: { + borderColor: 'rgb(96, 57, 74)' + } + }, + // 概要节点样式 + generalization: { + fillColor: '#fff', + borderColor: '#333', + color: '#333', + active: { + borderColor: 'rgb(96, 57, 74)' + } + } +}) diff --git a/simple-mind-map/src/themes/classic.js b/simple-mind-map/src/themes/classic.js index d3d4f918..d501a71c 100644 --- a/simple-mind-map/src/themes/classic.js +++ b/simple-mind-map/src/themes/classic.js @@ -1,67 +1,68 @@ -import defaultTheme from './default'; -import merge from 'deepmerge'; +import defaultTheme from './default' +import merge from 'deepmerge' -/** - * @Author: 王林 - * @Date: 2021-04-11 15:22:18 +/** + * @Author: 王林 + * @Date: 2021-04-11 15:22:18 * @Desc: 脑图经典 */ export default merge(defaultTheme, { - // 连线的颜色 - lineColor: '#fff', - // 连线的粗细 - lineWidth: 3, - // 概要连线的粗细 - generalizationLineWidth: 3, - // 概要连线的颜色 - generalizationLineColor: '#fff', - // 背景颜色 - backgroundColor: 'rgb(58, 65, 68)', - // 背景图片 - backgroundImage: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAIAAAACDbGyAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDowQzg5QTQ0NDhENzgxMUUzOENGREE4QTg0RDgzRTZDNyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDowQzg5QTQ0NThENzgxMUUzOENGREE4QTg0RDgzRTZDNyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkMwOEQ1NDRGOEQ3NzExRTM4Q0ZEQThBODREODNFNkM3IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkMwOEQ1NDUwOEQ3NzExRTM4Q0ZEQThBODREODNFNkM3Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+e9P33AAAACVJREFUeNpisXJ0YUACTAyoAMr/+eM7EGGRZ4FQ7BycEAZAgAEAHbEGtkoQm/wAAAAASUVORK5CYII=', - // 背景重复 - backgroundRepeat: 'repeat', - // 根节点样式 - root: { - fillColor: 'rgb(233, 223, 152)', - color: '#333', - fontSize: 24, - borderRadius: 21, - active: { - fillColor: 'rgb(254, 219, 0)', - borderColor: 'transparent' - } - }, - // 二级节点样式 - second: { - fillColor: 'rgb(164, 197, 192)', - borderColor: 'transparent', - color: '#333', - fontSize: 16, - borderRadius: 10, - active: { - fillColor: 'rgb(254, 219, 0)', - borderColor: 'transparent' - } - }, - // 三级及以下节点样式 - node: { - fontSize: 12, - color: '#fff', - fontWeight: 'bold', - active: { - fillColor: 'rgb(254, 219, 0)', - borderColor: 'transparent' - } - }, - // 概要节点样式 - generalization: { - fillColor: '#fff', - borderColor: 'transparent', - color: '#333', - active: { - fillColor: 'rgb(254, 219, 0)', - borderColor: 'transparent' - } + // 连线的颜色 + lineColor: '#fff', + // 连线的粗细 + lineWidth: 3, + // 概要连线的粗细 + generalizationLineWidth: 3, + // 概要连线的颜色 + generalizationLineColor: '#fff', + // 背景颜色 + backgroundColor: 'rgb(58, 65, 68)', + // 背景图片 + backgroundImage: + 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAIAAAACDbGyAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDowQzg5QTQ0NDhENzgxMUUzOENGREE4QTg0RDgzRTZDNyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDowQzg5QTQ0NThENzgxMUUzOENGREE4QTg0RDgzRTZDNyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkMwOEQ1NDRGOEQ3NzExRTM4Q0ZEQThBODREODNFNkM3IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkMwOEQ1NDUwOEQ3NzExRTM4Q0ZEQThBODREODNFNkM3Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+e9P33AAAACVJREFUeNpisXJ0YUACTAyoAMr/+eM7EGGRZ4FQ7BycEAZAgAEAHbEGtkoQm/wAAAAASUVORK5CYII=', + // 背景重复 + backgroundRepeat: 'repeat', + // 根节点样式 + root: { + fillColor: 'rgb(233, 223, 152)', + color: '#333', + fontSize: 24, + borderRadius: 21, + active: { + fillColor: 'rgb(254, 219, 0)', + borderColor: 'transparent' } -}) \ No newline at end of file + }, + // 二级节点样式 + second: { + fillColor: 'rgb(164, 197, 192)', + borderColor: 'transparent', + color: '#333', + fontSize: 16, + borderRadius: 10, + active: { + fillColor: 'rgb(254, 219, 0)', + borderColor: 'transparent' + } + }, + // 三级及以下节点样式 + node: { + fontSize: 12, + color: '#fff', + fontWeight: 'bold', + active: { + fillColor: 'rgb(254, 219, 0)', + borderColor: 'transparent' + } + }, + // 概要节点样式 + generalization: { + fillColor: '#fff', + borderColor: 'transparent', + color: '#333', + active: { + fillColor: 'rgb(254, 219, 0)', + borderColor: 'transparent' + } + } +}) diff --git a/simple-mind-map/src/themes/classic2.js b/simple-mind-map/src/themes/classic2.js index 6c472f16..2e00a182 100644 --- a/simple-mind-map/src/themes/classic2.js +++ b/simple-mind-map/src/themes/classic2.js @@ -1,59 +1,59 @@ -import defaultTheme from './default'; -import merge from 'deepmerge'; +import defaultTheme from './default' +import merge from 'deepmerge' -/** - * @Author: 王林 - * @Date: 2021-04-11 15:22:18 +/** + * @Author: 王林 + * @Date: 2021-04-11 15:22:18 * @Desc: 经典2 */ export default merge(defaultTheme, { - // 连线的颜色 - lineColor: 'rgb(51, 51, 51)', - // 连线的粗细 - lineWidth: 2, - // 概要连线的粗细 - generalizationLineWidth: 3, - // 概要连线的颜色 - generalizationLineColor: 'rgb(51, 51, 51)', - // 背景颜色 - backgroundColor: '#fff', - // 根节点样式 - root: { - fillColor: 'rgb(18, 187, 55)', - color: '#fff', - fontSize: 24, - borderRadius: 10, - active: { - borderColor: 'rgb(51, 51, 51)' - } - }, - // 二级节点样式 - second: { - fillColor: 'rgb(241, 242, 241)', - borderColor: 'transparent', - color: '#1a1a1a', - fontSize: 18, - borderRadius: 10, - active: { - borderColor: 'rgb(51, 51, 51)' - } - }, - // 三级及以下节点样式 - node: { - fontSize: 14, - color: '#1a1a1a', - active: { - borderColor: 'rgb(51, 51, 51)' - } - }, - // 概要节点样式 - generalization: { - fillColor: '#fff', - borderColor: 'rgb(51, 51, 51)', - borderWidth: 2, - color: '#1a1a1a', - active: { - borderColor: 'rgb(18, 187, 55)' - } + // 连线的颜色 + lineColor: 'rgb(51, 51, 51)', + // 连线的粗细 + lineWidth: 2, + // 概要连线的粗细 + generalizationLineWidth: 3, + // 概要连线的颜色 + generalizationLineColor: 'rgb(51, 51, 51)', + // 背景颜色 + backgroundColor: '#fff', + // 根节点样式 + root: { + fillColor: 'rgb(18, 187, 55)', + color: '#fff', + fontSize: 24, + borderRadius: 10, + active: { + borderColor: 'rgb(51, 51, 51)' } -}) \ No newline at end of file + }, + // 二级节点样式 + second: { + fillColor: 'rgb(241, 242, 241)', + borderColor: 'transparent', + color: '#1a1a1a', + fontSize: 18, + borderRadius: 10, + active: { + borderColor: 'rgb(51, 51, 51)' + } + }, + // 三级及以下节点样式 + node: { + fontSize: 14, + color: '#1a1a1a', + active: { + borderColor: 'rgb(51, 51, 51)' + } + }, + // 概要节点样式 + generalization: { + fillColor: '#fff', + borderColor: 'rgb(51, 51, 51)', + borderWidth: 2, + color: '#1a1a1a', + active: { + borderColor: 'rgb(18, 187, 55)' + } + } +}) diff --git a/simple-mind-map/src/themes/classic3.js b/simple-mind-map/src/themes/classic3.js index 8a15fc68..f8e10b08 100644 --- a/simple-mind-map/src/themes/classic3.js +++ b/simple-mind-map/src/themes/classic3.js @@ -1,62 +1,62 @@ -import defaultTheme from './default'; -import merge from 'deepmerge'; +import defaultTheme from './default' +import merge from 'deepmerge' -/** - * @Author: 王林 - * @Date: 2021-04-11 15:22:18 +/** + * @Author: 王林 + * @Date: 2021-04-11 15:22:18 * @Desc: 经典3 */ export default merge(defaultTheme, { - // 连线的颜色 - lineColor: 'rgb(94, 202, 110)', - // 连线的粗细 - lineWidth: 2, - // 概要连线的粗细 - generalizationLineWidth: 3, - // 概要连线的颜色 - generalizationLineColor: '#1a1a1a', - // 背景颜色 - backgroundColor: 'rgb(241, 241, 241)', - // 根节点样式 - root: { - fillColor: 'rgb(255, 245, 214)', - color: '#1a1a1a', - fontSize: 24, - borderRadius: 10, - borderColor: 'rgb(249, 199, 84)', - borderWidth: 1, - active: { - borderColor: 'rgb(94, 202, 110)' - } - }, - // 二级节点样式 - second: { - fillColor: 'rgb(255, 245, 214)', - borderColor: 'rgb(249, 199, 84)', - borderWidth: 1, - color: '#1a1a1a', - fontSize: 18, - borderRadius: 10, - active: { - borderColor: 'rgb(94, 202, 110)' - } - }, - // 三级及以下节点样式 - node: { - fontSize: 14, - color: '#1a1a1a', - active: { - borderColor: 'rgb(94, 202, 110)' - } - }, - // 概要节点样式 - generalization: { - fillColor: '#fff', - borderColor: '#1a1a1a', - color: '#1a1a1a', - borderWidth: 2, - active: { - borderColor: 'rgb(94, 202, 110)' - } + // 连线的颜色 + lineColor: 'rgb(94, 202, 110)', + // 连线的粗细 + lineWidth: 2, + // 概要连线的粗细 + generalizationLineWidth: 3, + // 概要连线的颜色 + generalizationLineColor: '#1a1a1a', + // 背景颜色 + backgroundColor: 'rgb(241, 241, 241)', + // 根节点样式 + root: { + fillColor: 'rgb(255, 245, 214)', + color: '#1a1a1a', + fontSize: 24, + borderRadius: 10, + borderColor: 'rgb(249, 199, 84)', + borderWidth: 1, + active: { + borderColor: 'rgb(94, 202, 110)' } -}) \ No newline at end of file + }, + // 二级节点样式 + second: { + fillColor: 'rgb(255, 245, 214)', + borderColor: 'rgb(249, 199, 84)', + borderWidth: 1, + color: '#1a1a1a', + fontSize: 18, + borderRadius: 10, + active: { + borderColor: 'rgb(94, 202, 110)' + } + }, + // 三级及以下节点样式 + node: { + fontSize: 14, + color: '#1a1a1a', + active: { + borderColor: 'rgb(94, 202, 110)' + } + }, + // 概要节点样式 + generalization: { + fillColor: '#fff', + borderColor: '#1a1a1a', + color: '#1a1a1a', + borderWidth: 2, + active: { + borderColor: 'rgb(94, 202, 110)' + } + } +}) diff --git a/simple-mind-map/src/themes/classic4.js b/simple-mind-map/src/themes/classic4.js index 03158edb..449ca317 100644 --- a/simple-mind-map/src/themes/classic4.js +++ b/simple-mind-map/src/themes/classic4.js @@ -1,65 +1,65 @@ -import defaultTheme from './default'; -import merge from 'deepmerge'; +import defaultTheme from './default' +import merge from 'deepmerge' -/** - * @Author: 王林 - * @Date: 2021-04-11 15:22:18 +/** + * @Author: 王林 + * @Date: 2021-04-11 15:22:18 * @Desc: 经典4 */ export default merge(defaultTheme, { - // 连线的颜色 - lineColor: 'rgb(30, 53, 86)', - // 连线的粗细 - lineWidth: 2, - // 概要连线的粗细 - generalizationLineWidth: 2, - // 概要连线的颜色 - generalizationLineColor: 'rgb(56, 123, 233)', - // 背景颜色 - backgroundColor: 'rgb(241, 241, 241)', - // 根节点样式 - root: { - fillColor: 'rgb(30, 53, 86)', - color: '#fff', - fontSize: 24, - borderRadius: 10, - borderColor: 'rgb(189, 197, 201)', - borderWidth: 2, - active: { - borderColor: 'rgb(169, 218, 218)' - } - }, - // 二级节点样式 - second: { - fillColor: 'rgb(169, 218, 218)', - borderColor: 'rgb(30, 53, 86)', - borderWidth: 2, - color: '#fff', - fontSize: 18, - borderRadius: 10, - active: { - borderColor: 'rgb(56, 123, 233)' - } - }, - // 三级及以下节点样式 - node: { - fontSize: 14, - color: 'rgb(30, 53, 86)', - borderColor: 'rgb(30, 53, 86)', - borderWidth: 1, - marginY: 20, - active: { - borderColor: 'rgb(169, 218, 218)' - } - }, - // 概要节点样式 - generalization: { - fillColor: 'rgb(56, 123, 233)', - borderColor: 'rgb(56, 123, 233)', - color: '#fff', - borderWidth: 0, - active: { - borderColor: 'rgb(169, 218, 218)' - } + // 连线的颜色 + lineColor: 'rgb(30, 53, 86)', + // 连线的粗细 + lineWidth: 2, + // 概要连线的粗细 + generalizationLineWidth: 2, + // 概要连线的颜色 + generalizationLineColor: 'rgb(56, 123, 233)', + // 背景颜色 + backgroundColor: 'rgb(241, 241, 241)', + // 根节点样式 + root: { + fillColor: 'rgb(30, 53, 86)', + color: '#fff', + fontSize: 24, + borderRadius: 10, + borderColor: 'rgb(189, 197, 201)', + borderWidth: 2, + active: { + borderColor: 'rgb(169, 218, 218)' } -}) \ No newline at end of file + }, + // 二级节点样式 + second: { + fillColor: 'rgb(169, 218, 218)', + borderColor: 'rgb(30, 53, 86)', + borderWidth: 2, + color: '#fff', + fontSize: 18, + borderRadius: 10, + active: { + borderColor: 'rgb(56, 123, 233)' + } + }, + // 三级及以下节点样式 + node: { + fontSize: 14, + color: 'rgb(30, 53, 86)', + borderColor: 'rgb(30, 53, 86)', + borderWidth: 1, + marginY: 20, + active: { + borderColor: 'rgb(169, 218, 218)' + } + }, + // 概要节点样式 + generalization: { + fillColor: 'rgb(56, 123, 233)', + borderColor: 'rgb(56, 123, 233)', + color: '#fff', + borderWidth: 0, + active: { + borderColor: 'rgb(169, 218, 218)' + } + } +}) diff --git a/simple-mind-map/src/themes/classicBlue.js b/simple-mind-map/src/themes/classicBlue.js index b4295082..a085aa60 100644 --- a/simple-mind-map/src/themes/classicBlue.js +++ b/simple-mind-map/src/themes/classicBlue.js @@ -1,56 +1,56 @@ -import defaultTheme from './default'; -import merge from 'deepmerge'; +import defaultTheme from './default' +import merge from 'deepmerge' -/** - * @Author: 王林 - * @Date: 2021-04-11 15:22:18 +/** + * @Author: 王林 + * @Date: 2021-04-11 15:22:18 * @Desc: 经典蓝 */ export default merge(defaultTheme, { - // 连线的颜色 - lineColor: 'rgb(51, 51, 51)', - // 连线的粗细 - lineWidth: 2, - // 概要连线的粗细 - generalizationLineWidth: 2, - // 概要连线的颜色 - generalizationLineColor: 'rgb(51, 51, 51)', - // 背景颜色 - backgroundColor: 'rgb(239, 248, 250)', - // 根节点样式 - root: { - fillColor: 'rgb(255, 255, 255)', - color: '#222', - active: { - borderColor: 'rgb(94, 199, 248)' - } - }, - // 二级节点样式 - second: { - fillColor: 'rgb(255, 255, 255)', - color: '#222', - borderColor: 'rgb(255, 255, 255)', - borderWidth: 1, - fontSize: 14, - active: { - borderColor: 'rgb(94, 199, 248)' - } - }, - // 三级及以下节点样式 - node: { - fontSize: 12, - color: '#333', - active: { - borderColor: 'rgb(94, 199, 248)' - } - }, - // 概要节点样式 - generalization: { - fillColor: '#fff', - borderColor: 'rgb(51, 51, 51)', - color: '#333', - active: { - borderColor: 'rgb(94, 199, 248)' - } + // 连线的颜色 + lineColor: 'rgb(51, 51, 51)', + // 连线的粗细 + lineWidth: 2, + // 概要连线的粗细 + generalizationLineWidth: 2, + // 概要连线的颜色 + generalizationLineColor: 'rgb(51, 51, 51)', + // 背景颜色 + backgroundColor: 'rgb(239, 248, 250)', + // 根节点样式 + root: { + fillColor: 'rgb(255, 255, 255)', + color: '#222', + active: { + borderColor: 'rgb(94, 199, 248)' } -}) \ No newline at end of file + }, + // 二级节点样式 + second: { + fillColor: 'rgb(255, 255, 255)', + color: '#222', + borderColor: 'rgb(255, 255, 255)', + borderWidth: 1, + fontSize: 14, + active: { + borderColor: 'rgb(94, 199, 248)' + } + }, + // 三级及以下节点样式 + node: { + fontSize: 12, + color: '#333', + active: { + borderColor: 'rgb(94, 199, 248)' + } + }, + // 概要节点样式 + generalization: { + fillColor: '#fff', + borderColor: 'rgb(51, 51, 51)', + color: '#333', + active: { + borderColor: 'rgb(94, 199, 248)' + } + } +}) diff --git a/simple-mind-map/src/themes/classicGreen.js b/simple-mind-map/src/themes/classicGreen.js index 1c1f9ebc..c6e7648a 100644 --- a/simple-mind-map/src/themes/classicGreen.js +++ b/simple-mind-map/src/themes/classicGreen.js @@ -1,55 +1,55 @@ -import defaultTheme from './default'; -import merge from 'deepmerge'; +import defaultTheme from './default' +import merge from 'deepmerge' -/** - * @Author: 王林 - * @Date: 2021-04-11 15:22:18 +/** + * @Author: 王林 + * @Date: 2021-04-11 15:22:18 * @Desc: 经典绿 */ export default merge(defaultTheme, { - // 连线的颜色 - lineColor: 'rgb(123, 199, 120)', - // 背景颜色 - backgroundColor: 'rgb(236, 245, 231)', - // 概要连线的粗细 - generalizationLineWidth: 2, - // 概要连线的颜色 - generalizationLineColor: 'rgb(123, 199, 120)', - // 根节点样式 - root: { - fillColor: 'rgb(253, 244, 217)', - color: '#222', - active: { - borderColor: 'rgb(94, 199, 248)' - } - }, - // 二级节点样式 - second: { - fillColor: 'rgb(253, 244, 217)', - color: '#222', - borderColor: 'rgb(242, 200, 104)', - borderWidth: 1, - fontSize: 14, - active: { - borderColor: 'rgb(94, 199, 248)' - } - }, - // 三级及以下节点样式 - node: { - fontSize: 12, - color: '#333', - active: { - borderColor: 'rgb(94, 199, 248)' - } - }, - // 概要节点样式 - generalization: { - fillColor: 'rgb(123, 199, 120)', - borderColor: 'transparent', - borderWidth: 2, - color: '#fff', - active: { - borderColor: 'rgb(94, 199, 248)' - } + // 连线的颜色 + lineColor: 'rgb(123, 199, 120)', + // 背景颜色 + backgroundColor: 'rgb(236, 245, 231)', + // 概要连线的粗细 + generalizationLineWidth: 2, + // 概要连线的颜色 + generalizationLineColor: 'rgb(123, 199, 120)', + // 根节点样式 + root: { + fillColor: 'rgb(253, 244, 217)', + color: '#222', + active: { + borderColor: 'rgb(94, 199, 248)' } -}) \ No newline at end of file + }, + // 二级节点样式 + second: { + fillColor: 'rgb(253, 244, 217)', + color: '#222', + borderColor: 'rgb(242, 200, 104)', + borderWidth: 1, + fontSize: 14, + active: { + borderColor: 'rgb(94, 199, 248)' + } + }, + // 三级及以下节点样式 + node: { + fontSize: 12, + color: '#333', + active: { + borderColor: 'rgb(94, 199, 248)' + } + }, + // 概要节点样式 + generalization: { + fillColor: 'rgb(123, 199, 120)', + borderColor: 'transparent', + borderWidth: 2, + color: '#fff', + active: { + borderColor: 'rgb(94, 199, 248)' + } + } +}) diff --git a/simple-mind-map/src/themes/dark.js b/simple-mind-map/src/themes/dark.js index 0032655e..475a904e 100644 --- a/simple-mind-map/src/themes/dark.js +++ b/simple-mind-map/src/themes/dark.js @@ -1,58 +1,58 @@ -import defaultTheme from './default'; -import merge from 'deepmerge'; +import defaultTheme from './default' +import merge from 'deepmerge' -/** - * @Author: 王林 - * @Date: 2021-04-11 15:22:18 +/** + * @Author: 王林 + * @Date: 2021-04-11 15:22:18 * @Desc: 暗色 */ export default merge(defaultTheme, { - // 连线的颜色 - lineColor: 'rgb(17, 68, 23)', - // 连线的粗细 - lineWidth: 2, - // 概要连线的粗细 - generalizationLineWidth: 2, - // 概要连线的颜色 - generalizationLineColor: '#fff', - // 背景颜色 - backgroundColor: 'rgb(15, 16, 17)', - // 根节点样式 - root: { - fillColor: 'rgb(28, 178, 43)', - color: '#fff', - fontSize: 24, - borderRadius: 10, - active: { - borderColor: 'rgb(17, 68, 23)' - } - }, - // 二级节点样式 - second: { - fillColor: 'rgb(55, 56, 58)', - color: 'rgb(147,148,149)', - fontSize: 18, - borderRadius: 10, - borderWidth: 0, - active: { - borderColor: 'rgb(17, 68, 23)' - } - }, - // 三级及以下节点样式 - node: { - fontSize: 14, - color: 'rgb(147, 148, 149)', - active: { - borderColor: 'rgb(17, 68, 23)' - } - }, - // 概要节点样式 - generalization: { - fillColor: '#fff', - borderColor: 'transparent', - color: '#333', - active: { - borderColor: 'rgb(17, 68, 23)' - } + // 连线的颜色 + lineColor: 'rgb(17, 68, 23)', + // 连线的粗细 + lineWidth: 2, + // 概要连线的粗细 + generalizationLineWidth: 2, + // 概要连线的颜色 + generalizationLineColor: '#fff', + // 背景颜色 + backgroundColor: 'rgb(15, 16, 17)', + // 根节点样式 + root: { + fillColor: 'rgb(28, 178, 43)', + color: '#fff', + fontSize: 24, + borderRadius: 10, + active: { + borderColor: 'rgb(17, 68, 23)' } -}) \ No newline at end of file + }, + // 二级节点样式 + second: { + fillColor: 'rgb(55, 56, 58)', + color: 'rgb(147,148,149)', + fontSize: 18, + borderRadius: 10, + borderWidth: 0, + active: { + borderColor: 'rgb(17, 68, 23)' + } + }, + // 三级及以下节点样式 + node: { + fontSize: 14, + color: 'rgb(147, 148, 149)', + active: { + borderColor: 'rgb(17, 68, 23)' + } + }, + // 概要节点样式 + generalization: { + fillColor: '#fff', + borderColor: 'transparent', + color: '#333', + active: { + borderColor: 'rgb(17, 68, 23)' + } + } +}) diff --git a/simple-mind-map/src/themes/dark2.js b/simple-mind-map/src/themes/dark2.js index 99173524..d55ab41b 100644 --- a/simple-mind-map/src/themes/dark2.js +++ b/simple-mind-map/src/themes/dark2.js @@ -1,60 +1,60 @@ -import defaultTheme from './default'; -import merge from 'deepmerge'; +import defaultTheme from './default' +import merge from 'deepmerge' -/** - * @Author: 王林 - * @Date: 2021-04-11 15:22:18 +/** + * @Author: 王林 + * @Date: 2021-04-11 15:22:18 * @Desc: 暗色2 */ export default merge(defaultTheme, { - // 连线的颜色 - lineColor: 'rgb(75, 81, 78)', - lineWidth: 3, - // 概要连线的粗细 - generalizationLineWidth: 3, - // 概要连线的颜色 - generalizationLineColor: 'rgb(255, 119, 34)', - // 背景颜色 - backgroundColor: 'rgb(27, 31, 34)', - // 根节点样式 - root: { - fillColor: 'rgb(36, 179, 96)', - color: '#fff', - borderColor: '', - borderWidth: 0, - active: { - borderColor: 'rgb(254, 199, 13)', - borderWidth: 3, - } - }, - // 二级节点样式 - second: { - fillColor: 'rgb(254, 199, 13)', - color: 'rgb(0, 0, 0)', - borderColor: '', - borderWidth: 0, - fontSize: 14, - active: { - borderColor: 'rgb(36, 179, 96)', - borderWidth: 2 - } - }, - // 三级及以下节点样式 - node: { - fontSize: 12, - color: 'rgb(204, 204, 204)', - active: { - borderColor: 'rgb(254, 199, 13)' - } - }, - // 概要节点样式 - generalization: { - fillColor: 'transparent', - borderColor: 'rgb(255, 119, 34)', - borderWidth: 2, - color: 'rgb(204, 204, 204)', - active: { - borderColor: 'rgb(254, 199, 13)' - } + // 连线的颜色 + lineColor: 'rgb(75, 81, 78)', + lineWidth: 3, + // 概要连线的粗细 + generalizationLineWidth: 3, + // 概要连线的颜色 + generalizationLineColor: 'rgb(255, 119, 34)', + // 背景颜色 + backgroundColor: 'rgb(27, 31, 34)', + // 根节点样式 + root: { + fillColor: 'rgb(36, 179, 96)', + color: '#fff', + borderColor: '', + borderWidth: 0, + active: { + borderColor: 'rgb(254, 199, 13)', + borderWidth: 3 } -}) \ No newline at end of file + }, + // 二级节点样式 + second: { + fillColor: 'rgb(254, 199, 13)', + color: 'rgb(0, 0, 0)', + borderColor: '', + borderWidth: 0, + fontSize: 14, + active: { + borderColor: 'rgb(36, 179, 96)', + borderWidth: 2 + } + }, + // 三级及以下节点样式 + node: { + fontSize: 12, + color: 'rgb(204, 204, 204)', + active: { + borderColor: 'rgb(254, 199, 13)' + } + }, + // 概要节点样式 + generalization: { + fillColor: 'transparent', + borderColor: 'rgb(255, 119, 34)', + borderWidth: 2, + color: 'rgb(204, 204, 204)', + active: { + borderColor: 'rgb(254, 199, 13)' + } + } +}) diff --git a/simple-mind-map/src/themes/default.js b/simple-mind-map/src/themes/default.js index e946c537..7170e033 100644 --- a/simple-mind-map/src/themes/default.js +++ b/simple-mind-map/src/themes/default.js @@ -1,134 +1,144 @@ -/** - * @Author: 王林 - * @Date: 2021-04-11 10:19:55 - * @Desc: 默认主题 +/** + * @Author: 王林 + * @Date: 2021-04-11 10:19:55 + * @Desc: 默认主题 */ export default { - // 节点内边距 - paddingX: 15, - paddingY: 5, - // 图片显示的最大宽度 - imgMaxWidth: 100, - // 图片显示的最大高度 - imgMaxHeight: 100, - // icon的大小 - iconSize: 20, - // 连线的粗细 - lineWidth: 1, - // 连线的颜色 - lineColor: '#549688', - // 连线样式 - lineDasharray: 'none', - // 连线风格 - lineStyle: 'straight',// 针对logicalStructure、mindMap两种结构。曲线(curve)、直线(straight)、直连(direct) - // 概要连线的粗细 - generalizationLineWidth: 1, - // 概要连线的颜色 - generalizationLineColor: '#549688', - // 概要曲线距节点的距离 - generalizationLineMargin: 0, - // 概要节点距节点的距离 - generalizationNodeMargin: 20, - // 背景颜色 - backgroundColor: '#fafafa', - // 背景图片 - backgroundImage: 'none', - // 背景重复 - backgroundRepeat: 'no-repeat', - // 根节点样式 - root: { - shape: 'rectangle', - fillColor: '#549688', - fontFamily: '微软雅黑, Microsoft YaHei', - color: '#fff', - fontSize: 16, - fontWeight: 'bold', - fontStyle: 'normal', - lineHeight: 1.5, - borderColor: 'transparent', - borderWidth: 0, - borderDasharray: 'none', - borderRadius: 5, - textDecoration: 'none', - active: { - borderColor: 'rgb(57, 80, 96)', - borderWidth: 3, - borderDasharray: 'none', - } - }, - // 二级节点样式 - second: { - shape: 'rectangle', - marginX: 100, - marginY: 40, - fillColor: '#fff', - fontFamily: '微软雅黑, Microsoft YaHei', - color: '#565656', - fontSize: 16, - fontWeight: 'noraml', - fontStyle: 'normal', - lineHeight: 1.5, - borderColor: '#549688', - borderWidth: 1, - borderDasharray: 'none', - borderRadius: 5, - textDecoration: 'none', - active: { - borderColor: 'rgb(57, 80, 96)', - borderWidth: 3, - borderDasharray: 'none', - } - }, - // 三级及以下节点样式 - node: { - shape: 'rectangle', - marginX: 50, - marginY: 0, - fillColor: 'transparent', - fontFamily: '微软雅黑, Microsoft YaHei', - color: '#6a6d6c', - fontSize: 14, - fontWeight: 'noraml', - fontStyle: 'normal', - lineHeight: 1.5, - borderColor: 'transparent', - borderWidth: 0, - borderRadius: 5, - borderDasharray: 'none', - textDecoration: 'none', - active: { - borderColor: 'rgb(57, 80, 96)', - borderWidth: 3, - borderDasharray: 'none', - } - }, - // 概要节点样式 - generalization: { - shape: 'rectangle', - marginX: 100, - marginY: 40, - fillColor: '#fff', - fontFamily: '微软雅黑, Microsoft YaHei', - color: '#565656', - fontSize: 16, - fontWeight: 'noraml', - fontStyle: 'normal', - lineHeight: 1.5, - borderColor: '#549688', - borderWidth: 1, - borderDasharray: 'none', - borderRadius: 5, - textDecoration: 'none', - active: { - borderColor: 'rgb(57, 80, 96)', - borderWidth: 3, - borderDasharray: 'none', - } + // 节点内边距 + paddingX: 15, + paddingY: 5, + // 图片显示的最大宽度 + imgMaxWidth: 100, + // 图片显示的最大高度 + imgMaxHeight: 100, + // icon的大小 + iconSize: 20, + // 连线的粗细 + lineWidth: 1, + // 连线的颜色 + lineColor: '#549688', + // 连线样式 + lineDasharray: 'none', + // 连线风格 + lineStyle: 'straight', // 针对logicalStructure、mindMap两种结构。曲线(curve)、直线(straight)、直连(direct) + // 概要连线的粗细 + generalizationLineWidth: 1, + // 概要连线的颜色 + generalizationLineColor: '#549688', + // 概要曲线距节点的距离 + generalizationLineMargin: 0, + // 概要节点距节点的距离 + generalizationNodeMargin: 20, + // 背景颜色 + backgroundColor: '#fafafa', + // 背景图片 + backgroundImage: 'none', + // 背景重复 + backgroundRepeat: 'no-repeat', + // 根节点样式 + root: { + shape: 'rectangle', + fillColor: '#549688', + fontFamily: '微软雅黑, Microsoft YaHei', + color: '#fff', + fontSize: 16, + fontWeight: 'bold', + fontStyle: 'normal', + lineHeight: 1.5, + borderColor: 'transparent', + borderWidth: 0, + borderDasharray: 'none', + borderRadius: 5, + textDecoration: 'none', + active: { + borderColor: 'rgb(57, 80, 96)', + borderWidth: 3, + borderDasharray: 'none' } + }, + // 二级节点样式 + second: { + shape: 'rectangle', + marginX: 100, + marginY: 40, + fillColor: '#fff', + fontFamily: '微软雅黑, Microsoft YaHei', + color: '#565656', + fontSize: 16, + fontWeight: 'noraml', + fontStyle: 'normal', + lineHeight: 1.5, + borderColor: '#549688', + borderWidth: 1, + borderDasharray: 'none', + borderRadius: 5, + textDecoration: 'none', + active: { + borderColor: 'rgb(57, 80, 96)', + borderWidth: 3, + borderDasharray: 'none' + } + }, + // 三级及以下节点样式 + node: { + shape: 'rectangle', + marginX: 50, + marginY: 0, + fillColor: 'transparent', + fontFamily: '微软雅黑, Microsoft YaHei', + color: '#6a6d6c', + fontSize: 14, + fontWeight: 'noraml', + fontStyle: 'normal', + lineHeight: 1.5, + borderColor: 'transparent', + borderWidth: 0, + borderRadius: 5, + borderDasharray: 'none', + textDecoration: 'none', + active: { + borderColor: 'rgb(57, 80, 96)', + borderWidth: 3, + borderDasharray: 'none' + } + }, + // 概要节点样式 + generalization: { + shape: 'rectangle', + marginX: 100, + marginY: 40, + fillColor: '#fff', + fontFamily: '微软雅黑, Microsoft YaHei', + color: '#565656', + fontSize: 16, + fontWeight: 'noraml', + fontStyle: 'normal', + lineHeight: 1.5, + borderColor: '#549688', + borderWidth: 1, + borderDasharray: 'none', + borderRadius: 5, + textDecoration: 'none', + active: { + borderColor: 'rgb(57, 80, 96)', + borderWidth: 3, + borderDasharray: 'none' + } + } } // 支持激活样式的属性 // 简单来说,会改变节点大小的都不支持在激活时设置,为了性能考虑,节点切换激活态时不会重新计算节点大小 -export const supportActiveStyle = ['fillColor', 'color', 'fontWeight', 'fontStyle', 'borderColor', 'borderWidth', 'borderDasharray', 'borderRadius', 'textDecoration'] +export const supportActiveStyle = [ + 'fillColor', + 'color', + 'fontWeight', + 'fontStyle', + 'borderColor', + 'borderWidth', + 'borderDasharray', + 'borderRadius', + 'textDecoration' +] -export const lineStyleProps = ['lineColor', 'lineDasharray', 'lineWidth'] \ No newline at end of file +export const lineStyleProps = ['lineColor', 'lineDasharray', 'lineWidth'] diff --git a/simple-mind-map/src/themes/earthYellow.js b/simple-mind-map/src/themes/earthYellow.js index 618914a6..e22998f3 100644 --- a/simple-mind-map/src/themes/earthYellow.js +++ b/simple-mind-map/src/themes/earthYellow.js @@ -1,53 +1,53 @@ -import defaultTheme from './default'; -import merge from 'deepmerge'; +import defaultTheme from './default' +import merge from 'deepmerge' -/** - * @Author: 王林 - * @Date: 2021-04-11 15:22:18 +/** + * @Author: 王林 + * @Date: 2021-04-11 15:22:18 * @Desc: 泥土黄 */ export default merge(defaultTheme, { - // 连线的颜色 - lineColor: 'rgb(191, 147, 115)', - // 背景颜色 - backgroundColor: 'rgb(251, 251, 251)', - // 概要连线的粗细 - generalizationLineWidth: 1, - // 概要连线的颜色 - generalizationLineColor: '#333', - // 根节点样式 - root: { - fillColor: 'rgb(191, 147, 115)', - active: { - borderColor: 'rgb(96, 73, 57)' - } - }, - // 二级节点样式 - second: { - fillColor: 'rgb(246, 242, 238)', - color: '#333', - borderColor: 'rgb(191, 147, 115)', - borderWidth: 1, - fontSize: 14, - active: { - borderColor: 'rgb(96, 73, 57)' - } - }, - // 三级及以下节点样式 - node: { - fontSize: 12, - color: '#333', - active: { - borderColor: 'rgb(96, 73, 57)' - } - }, - // 概要节点样式 - generalization: { - fillColor: '#fff', - borderColor: '#333', - color: '#333', - active: { - borderColor: 'rgb(96, 73, 57)' - } + // 连线的颜色 + lineColor: 'rgb(191, 147, 115)', + // 背景颜色 + backgroundColor: 'rgb(251, 251, 251)', + // 概要连线的粗细 + generalizationLineWidth: 1, + // 概要连线的颜色 + generalizationLineColor: '#333', + // 根节点样式 + root: { + fillColor: 'rgb(191, 147, 115)', + active: { + borderColor: 'rgb(96, 73, 57)' } -}) \ No newline at end of file + }, + // 二级节点样式 + second: { + fillColor: 'rgb(246, 242, 238)', + color: '#333', + borderColor: 'rgb(191, 147, 115)', + borderWidth: 1, + fontSize: 14, + active: { + borderColor: 'rgb(96, 73, 57)' + } + }, + // 三级及以下节点样式 + node: { + fontSize: 12, + color: '#333', + active: { + borderColor: 'rgb(96, 73, 57)' + } + }, + // 概要节点样式 + generalization: { + fillColor: '#fff', + borderColor: '#333', + color: '#333', + active: { + borderColor: 'rgb(96, 73, 57)' + } + } +}) diff --git a/simple-mind-map/src/themes/freshGreen.js b/simple-mind-map/src/themes/freshGreen.js index bcd278d0..61634caa 100644 --- a/simple-mind-map/src/themes/freshGreen.js +++ b/simple-mind-map/src/themes/freshGreen.js @@ -1,40 +1,40 @@ -import defaultTheme from './default'; -import merge from 'deepmerge'; +import defaultTheme from './default' +import merge from 'deepmerge' -/** - * @Author: 王林 - * @Date: 2021-04-11 15:22:18 - * @Desc: 清新绿 +/** + * @Author: 王林 + * @Date: 2021-04-11 15:22:18 + * @Desc: 清新绿 */ export default merge(defaultTheme, { - // 连线的颜色 - lineColor: '#333', - // 背景颜色 - backgroundColor: '#d1f6ec', - // 概要连线的粗细 - generalizationLineWidth: 1, - // 概要连线的颜色 - generalizationLineColor: '#333', - // 根节点样式 - root: { - fillColor: '#1fb27d' - }, - // 二级节点样式 - second: { - fillColor: '#fff', - color: '#565656', - borderColor: 'transparent', - borderWidth: 0 - }, - // 概要节点样式 - generalization: { - fillColor: '#fff', - borderColor: '#333', - color: '#333', - active: { - borderColor: 'rgb(57, 80, 96)', - borderWidth: 3, - borderDasharray: 'none', - } + // 连线的颜色 + lineColor: '#333', + // 背景颜色 + backgroundColor: '#d1f6ec', + // 概要连线的粗细 + generalizationLineWidth: 1, + // 概要连线的颜色 + generalizationLineColor: '#333', + // 根节点样式 + root: { + fillColor: '#1fb27d' + }, + // 二级节点样式 + second: { + fillColor: '#fff', + color: '#565656', + borderColor: 'transparent', + borderWidth: 0 + }, + // 概要节点样式 + generalization: { + fillColor: '#fff', + borderColor: '#333', + color: '#333', + active: { + borderColor: 'rgb(57, 80, 96)', + borderWidth: 3, + borderDasharray: 'none' } -}) \ No newline at end of file + } +}) diff --git a/simple-mind-map/src/themes/freshRed.js b/simple-mind-map/src/themes/freshRed.js index 750749b4..7fb10406 100644 --- a/simple-mind-map/src/themes/freshRed.js +++ b/simple-mind-map/src/themes/freshRed.js @@ -1,53 +1,53 @@ -import defaultTheme from './default'; -import merge from 'deepmerge'; +import defaultTheme from './default' +import merge from 'deepmerge' -/** - * @Author: 王林 - * @Date: 2021-04-11 15:22:18 +/** + * @Author: 王林 + * @Date: 2021-04-11 15:22:18 * @Desc: 清新红 */ export default merge(defaultTheme, { - // 连线的颜色 - lineColor: 'rgb(191, 115, 115)', - // 背景颜色 - backgroundColor: 'rgb(251, 251, 251)', - // 概要连线的粗细 - generalizationLineWidth: 1, - // 概要连线的颜色 - generalizationLineColor: '#333', - // 根节点样式 - root: { - fillColor: 'rgb(191, 115, 115)', - active: { - borderColor: 'rgb(96, 57, 57)' - } - }, - // 二级节点样式 - second: { - fillColor: 'rgb(246, 238, 238)', - color: '#333', - borderColor: 'rgb(191, 115, 115)', - borderWidth: 1, - fontSize: 14, - active: { - borderColor: 'rgb(96, 57, 57)' - } - }, - // 三级及以下节点样式 - node: { - fontSize: 12, - color: '#333', - active: { - borderColor: 'rgb(96, 57, 57)' - } - }, - // 概要节点样式 - generalization: { - fillColor: '#fff', - borderColor: '#333', - color: '#333', - active: { - borderColor: 'rgb(96, 57, 57)' - } + // 连线的颜色 + lineColor: 'rgb(191, 115, 115)', + // 背景颜色 + backgroundColor: 'rgb(251, 251, 251)', + // 概要连线的粗细 + generalizationLineWidth: 1, + // 概要连线的颜色 + generalizationLineColor: '#333', + // 根节点样式 + root: { + fillColor: 'rgb(191, 115, 115)', + active: { + borderColor: 'rgb(96, 57, 57)' } -}) \ No newline at end of file + }, + // 二级节点样式 + second: { + fillColor: 'rgb(246, 238, 238)', + color: '#333', + borderColor: 'rgb(191, 115, 115)', + borderWidth: 1, + fontSize: 14, + active: { + borderColor: 'rgb(96, 57, 57)' + } + }, + // 三级及以下节点样式 + node: { + fontSize: 12, + color: '#333', + active: { + borderColor: 'rgb(96, 57, 57)' + } + }, + // 概要节点样式 + generalization: { + fillColor: '#fff', + borderColor: '#333', + color: '#333', + active: { + borderColor: 'rgb(96, 57, 57)' + } + } +}) diff --git a/simple-mind-map/src/themes/gold.js b/simple-mind-map/src/themes/gold.js index 5bc12013..16df0763 100644 --- a/simple-mind-map/src/themes/gold.js +++ b/simple-mind-map/src/themes/gold.js @@ -1,59 +1,59 @@ -import defaultTheme from './default'; -import merge from 'deepmerge'; +import defaultTheme from './default' +import merge from 'deepmerge' -/** - * @Author: 王林 - * @Date: 2021-04-11 15:22:18 +/** + * @Author: 王林 + * @Date: 2021-04-11 15:22:18 * @Desc: 金色vip */ export default merge(defaultTheme, { - // 连线的颜色 - lineColor: 'rgb(51, 56, 62)', - lineWidth: 3, - // 概要连线的粗细 - generalizationLineWidth: 3, - // 概要连线的颜色 - generalizationLineColor: 'rgb(127, 93, 64)', - // 背景颜色 - backgroundColor: '#fff', - // 根节点样式 - root: { - fillColor: 'rgb(51, 56, 62)', - color: 'rgb(247, 208, 160)', - borderColor: '', - borderWidth: 0, - active: { - borderColor: 'rgb(247, 208, 160)', - borderWidth: 3, - } - }, - // 二级节点样式 - second: { - fillColor: 'rgb(239, 209, 176)', - color: 'rgb(81, 58, 42)', - borderColor: '', - borderWidth: 0, - fontSize: 14, - active: { - borderColor: 'rgb(51, 56, 62)', - borderWidth: 2 - } - }, - // 三级及以下节点样式 - node: { - fontSize: 12, - color: '#222', - active: { - borderColor: 'rgb(0, 192, 184)' - } - }, - // 概要节点样式 - generalization: { - fillColor: 'rgb(127, 93, 64)', - borderColor: 'transparent', - color: 'rgb(255, 214, 175)', - active: { - borderColor: 'rgb(51, 56, 62)' - } + // 连线的颜色 + lineColor: 'rgb(51, 56, 62)', + lineWidth: 3, + // 概要连线的粗细 + generalizationLineWidth: 3, + // 概要连线的颜色 + generalizationLineColor: 'rgb(127, 93, 64)', + // 背景颜色 + backgroundColor: '#fff', + // 根节点样式 + root: { + fillColor: 'rgb(51, 56, 62)', + color: 'rgb(247, 208, 160)', + borderColor: '', + borderWidth: 0, + active: { + borderColor: 'rgb(247, 208, 160)', + borderWidth: 3 } -}) \ No newline at end of file + }, + // 二级节点样式 + second: { + fillColor: 'rgb(239, 209, 176)', + color: 'rgb(81, 58, 42)', + borderColor: '', + borderWidth: 0, + fontSize: 14, + active: { + borderColor: 'rgb(51, 56, 62)', + borderWidth: 2 + } + }, + // 三级及以下节点样式 + node: { + fontSize: 12, + color: '#222', + active: { + borderColor: 'rgb(0, 192, 184)' + } + }, + // 概要节点样式 + generalization: { + fillColor: 'rgb(127, 93, 64)', + borderColor: 'transparent', + color: 'rgb(255, 214, 175)', + active: { + borderColor: 'rgb(51, 56, 62)' + } + } +}) diff --git a/simple-mind-map/src/themes/greenLeaf.js b/simple-mind-map/src/themes/greenLeaf.js index 947e9bc5..842f1424 100644 --- a/simple-mind-map/src/themes/greenLeaf.js +++ b/simple-mind-map/src/themes/greenLeaf.js @@ -1,60 +1,60 @@ -import defaultTheme from './default'; -import merge from 'deepmerge'; +import defaultTheme from './default' +import merge from 'deepmerge' -/** - * @Author: 王林 - * @Date: 2021-04-11 15:22:18 +/** + * @Author: 王林 + * @Date: 2021-04-11 15:22:18 * @Desc: 绿叶 */ export default merge(defaultTheme, { - // 连线的颜色 - lineColor: 'rgb(40, 193, 84)', - lineWidth: 3, - // 概要连线的粗细 - generalizationLineWidth: 3, - // 概要连线的颜色 - generalizationLineColor: 'rgb(251, 158, 0)', - // 背景颜色 - backgroundColor: 'rgb(238, 255, 243)', - // 根节点样式 - root: { - fillColor: 'rgb(25, 193, 73)', - color: '#fff', - borderColor: '', - borderWidth: 0, - active: { - borderColor: '#222', - borderWidth: 3, - } - }, - // 二级节点样式 - second: { - fillColor: '#fff', - color: 'rgb(69, 149, 96)', - borderColor: '', - borderWidth: 0, - fontSize: 14, - active: { - borderColor: 'rgb(25, 193, 73)', - borderWidth: 2 - } - }, - // 三级及以下节点样式 - node: { - fontSize: 12, - color: '#222', - active: { - borderColor: 'rgb(25, 193, 73)' - } - }, - // 概要节点样式 - generalization: { - fillColor: '#fff', - borderColor: 'rgb(251, 158, 0)', - borderWidth: 2, - color: 'rgb(51, 51, 51)', - active: { - borderColor: 'rgb(25, 193, 73)' - } + // 连线的颜色 + lineColor: 'rgb(40, 193, 84)', + lineWidth: 3, + // 概要连线的粗细 + generalizationLineWidth: 3, + // 概要连线的颜色 + generalizationLineColor: 'rgb(251, 158, 0)', + // 背景颜色 + backgroundColor: 'rgb(238, 255, 243)', + // 根节点样式 + root: { + fillColor: 'rgb(25, 193, 73)', + color: '#fff', + borderColor: '', + borderWidth: 0, + active: { + borderColor: '#222', + borderWidth: 3 } -}) \ No newline at end of file + }, + // 二级节点样式 + second: { + fillColor: '#fff', + color: 'rgb(69, 149, 96)', + borderColor: '', + borderWidth: 0, + fontSize: 14, + active: { + borderColor: 'rgb(25, 193, 73)', + borderWidth: 2 + } + }, + // 三级及以下节点样式 + node: { + fontSize: 12, + color: '#222', + active: { + borderColor: 'rgb(25, 193, 73)' + } + }, + // 概要节点样式 + generalization: { + fillColor: '#fff', + borderColor: 'rgb(251, 158, 0)', + borderWidth: 2, + color: 'rgb(51, 51, 51)', + active: { + borderColor: 'rgb(25, 193, 73)' + } + } +}) diff --git a/simple-mind-map/src/themes/index.js b/simple-mind-map/src/themes/index.js index ba794ec5..dd0bd3f8 100644 --- a/simple-mind-map/src/themes/index.js +++ b/simple-mind-map/src/themes/index.js @@ -8,8 +8,8 @@ import earthYellow from './earthYellow' import classic from './classic' import classic2 from './classic2' import classic3 from './classic3' -import classic4 from './classic4'; -import dark from './dark'; +import classic4 from './classic4' +import dark from './dark' import classicGreen from './classicGreen' import classicBlue from './classicBlue' import minions from './minions' @@ -22,26 +22,26 @@ import dark2 from './dark2' import skyGreen from './skyGreen' export default { - default: defaultTheme, - freshGreen, - blueSky, - brainImpairedPink, - romanticPurple, - freshRed, - earthYellow, - classic, - classic2, - classic3, - classic4, - dark, - classicGreen, - classicBlue, - minions, - pinkGrape, - mint, - gold, - vitalityOrange, - greenLeaf, - dark2, - skyGreen -} \ No newline at end of file + default: defaultTheme, + freshGreen, + blueSky, + brainImpairedPink, + romanticPurple, + freshRed, + earthYellow, + classic, + classic2, + classic3, + classic4, + dark, + classicGreen, + classicBlue, + minions, + pinkGrape, + mint, + gold, + vitalityOrange, + greenLeaf, + dark2, + skyGreen +} diff --git a/simple-mind-map/src/themes/minions.js b/simple-mind-map/src/themes/minions.js index 635f115a..0c862f6f 100644 --- a/simple-mind-map/src/themes/minions.js +++ b/simple-mind-map/src/themes/minions.js @@ -1,56 +1,56 @@ -import defaultTheme from './default'; -import merge from 'deepmerge'; +import defaultTheme from './default' +import merge from 'deepmerge' -/** - * @Author: 王林 - * @Date: 2021-04-11 15:22:18 +/** + * @Author: 王林 + * @Date: 2021-04-11 15:22:18 * @Desc: 小黄人 */ export default merge(defaultTheme, { - // 连线的颜色 - lineColor: 'rgb(51, 51, 51)', - lineWidth: 3, - // 概要连线的粗细 - generalizationLineWidth: 3, - // 概要连线的颜色 - generalizationLineColor: '#222', - // 背景颜色 - backgroundColor: 'rgb(248, 215, 49)', - // 根节点样式 - root: { - fillColor: 'rgb(55, 165, 255)', - borderColor: 'rgb(51, 51, 51)', - borderWidth: 3, - active: { - borderColor: 'rgb(255, 160, 36)' - } - }, - // 二级节点样式 - second: { - fillColor: 'rgb(255, 160, 36)', - color: '#222', - borderColor: 'rgb(51, 51, 51)', - borderWidth: 3, - fontSize: 14, - active: { - borderColor: 'rgb(55, 165, 255)' - } - }, - // 三级及以下节点样式 - node: { - fontSize: 12, - color: '#222', - active: { - borderColor: 'rgb(55, 165, 255)' - } - }, - // 概要节点样式 - generalization: { - borderColor: '#222', - borderWidth: 3, - color: '#222', - active: { - borderColor: 'rgb(55, 165, 255)' - } + // 连线的颜色 + lineColor: 'rgb(51, 51, 51)', + lineWidth: 3, + // 概要连线的粗细 + generalizationLineWidth: 3, + // 概要连线的颜色 + generalizationLineColor: '#222', + // 背景颜色 + backgroundColor: 'rgb(248, 215, 49)', + // 根节点样式 + root: { + fillColor: 'rgb(55, 165, 255)', + borderColor: 'rgb(51, 51, 51)', + borderWidth: 3, + active: { + borderColor: 'rgb(255, 160, 36)' } -}) \ No newline at end of file + }, + // 二级节点样式 + second: { + fillColor: 'rgb(255, 160, 36)', + color: '#222', + borderColor: 'rgb(51, 51, 51)', + borderWidth: 3, + fontSize: 14, + active: { + borderColor: 'rgb(55, 165, 255)' + } + }, + // 三级及以下节点样式 + node: { + fontSize: 12, + color: '#222', + active: { + borderColor: 'rgb(55, 165, 255)' + } + }, + // 概要节点样式 + generalization: { + borderColor: '#222', + borderWidth: 3, + color: '#222', + active: { + borderColor: 'rgb(55, 165, 255)' + } + } +}) diff --git a/simple-mind-map/src/themes/mint.js b/simple-mind-map/src/themes/mint.js index 505e4ba1..4be697e2 100644 --- a/simple-mind-map/src/themes/mint.js +++ b/simple-mind-map/src/themes/mint.js @@ -1,57 +1,57 @@ -import defaultTheme from './default'; -import merge from 'deepmerge'; +import defaultTheme from './default' +import merge from 'deepmerge' -/** - * @Author: 王林 - * @Date: 2021-04-11 15:22:18 +/** + * @Author: 王林 + * @Date: 2021-04-11 15:22:18 * @Desc: 薄荷 */ export default merge(defaultTheme, { - // 连线的颜色 - lineColor: 'rgb(104, 204, 202)', - lineWidth: 3, - // 概要连线的粗细 - generalizationLineWidth: 3, - // 概要连线的颜色 - generalizationLineColor: 'rgb(90, 206, 241)', - // 背景颜色 - backgroundColor: 'rgb(239, 255, 255)', - // 根节点样式 - root: { - fillColor: 'rgb(0, 192, 184)', - borderColor: '', - borderWidth: 0, - active: { - borderColor: 'rgb(255, 160, 36)', - borderWidth: 3, - } - }, - // 二级节点样式 - second: { - fillColor: '#fff', - color: '#222', - borderColor: 'rgb(184, 235, 233)', - borderWidth: 2, - fontSize: 14, - active: { - borderColor: 'rgb(0, 192, 184)' - } - }, - // 三级及以下节点样式 - node: { - fontSize: 12, - color: '#222', - active: { - borderColor: 'rgb(0, 192, 184)' - } - }, - // 概要节点样式 - generalization: { - fillColor: 'rgb(90, 206, 241)', - borderColor: 'transparent', - color: '#fff', - active: { - borderColor: 'rgb(0, 192, 184)' - } + // 连线的颜色 + lineColor: 'rgb(104, 204, 202)', + lineWidth: 3, + // 概要连线的粗细 + generalizationLineWidth: 3, + // 概要连线的颜色 + generalizationLineColor: 'rgb(90, 206, 241)', + // 背景颜色 + backgroundColor: 'rgb(239, 255, 255)', + // 根节点样式 + root: { + fillColor: 'rgb(0, 192, 184)', + borderColor: '', + borderWidth: 0, + active: { + borderColor: 'rgb(255, 160, 36)', + borderWidth: 3 } -}) \ No newline at end of file + }, + // 二级节点样式 + second: { + fillColor: '#fff', + color: '#222', + borderColor: 'rgb(184, 235, 233)', + borderWidth: 2, + fontSize: 14, + active: { + borderColor: 'rgb(0, 192, 184)' + } + }, + // 三级及以下节点样式 + node: { + fontSize: 12, + color: '#222', + active: { + borderColor: 'rgb(0, 192, 184)' + } + }, + // 概要节点样式 + generalization: { + fillColor: 'rgb(90, 206, 241)', + borderColor: 'transparent', + color: '#fff', + active: { + borderColor: 'rgb(0, 192, 184)' + } + } +}) diff --git a/simple-mind-map/src/themes/pinkGrape.js b/simple-mind-map/src/themes/pinkGrape.js index efe2e181..46a1744a 100644 --- a/simple-mind-map/src/themes/pinkGrape.js +++ b/simple-mind-map/src/themes/pinkGrape.js @@ -1,59 +1,59 @@ -import defaultTheme from './default'; -import merge from 'deepmerge'; +import defaultTheme from './default' +import merge from 'deepmerge' -/** - * @Author: 王林 - * @Date: 2021-04-11 15:22:18 +/** + * @Author: 王林 + * @Date: 2021-04-11 15:22:18 * @Desc: 粉红葡萄 */ export default merge(defaultTheme, { - // 连线的颜色 - lineColor: 'rgb(166, 101, 106)', - lineWidth: 3, - // 概要连线的粗细 - generalizationLineWidth: 3, - // 概要连线的颜色 - generalizationLineColor: '#fff', - // 背景颜色 - backgroundColor: 'rgb(255, 208, 211)', - // 根节点样式 - root: { - fillColor: 'rgb(139, 109, 225)', - borderColor: '', - borderWidth: 0, - active: { - borderColor: 'rgb(243, 104, 138)', - borderWidth: 2, - } - }, - // 二级节点样式 - second: { - fillColor: 'rgb(243, 104, 138)', - color: '#fff', - borderColor: '', - borderWidth: 0, - fontSize: 14, - active: { - borderColor: 'rgb(139, 109, 225)', - borderWidth: 2, - } - }, - // 三级及以下节点样式 - node: { - fontSize: 12, - color: '#222', - active: { - borderColor: 'rgb(139, 109, 225)' - } - }, - // 概要节点样式 - generalization: { - fillColor: '#fff', - borderColor: 'transparent', - color: '#222', - active: { - borderColor: 'rgb(139, 109, 225)', - borderWidth: 2, - } + // 连线的颜色 + lineColor: 'rgb(166, 101, 106)', + lineWidth: 3, + // 概要连线的粗细 + generalizationLineWidth: 3, + // 概要连线的颜色 + generalizationLineColor: '#fff', + // 背景颜色 + backgroundColor: 'rgb(255, 208, 211)', + // 根节点样式 + root: { + fillColor: 'rgb(139, 109, 225)', + borderColor: '', + borderWidth: 0, + active: { + borderColor: 'rgb(243, 104, 138)', + borderWidth: 2 } -}) \ No newline at end of file + }, + // 二级节点样式 + second: { + fillColor: 'rgb(243, 104, 138)', + color: '#fff', + borderColor: '', + borderWidth: 0, + fontSize: 14, + active: { + borderColor: 'rgb(139, 109, 225)', + borderWidth: 2 + } + }, + // 三级及以下节点样式 + node: { + fontSize: 12, + color: '#222', + active: { + borderColor: 'rgb(139, 109, 225)' + } + }, + // 概要节点样式 + generalization: { + fillColor: '#fff', + borderColor: 'transparent', + color: '#222', + active: { + borderColor: 'rgb(139, 109, 225)', + borderWidth: 2 + } + } +}) diff --git a/simple-mind-map/src/themes/romanticPurple.js b/simple-mind-map/src/themes/romanticPurple.js index 80ea550e..981ff9d0 100644 --- a/simple-mind-map/src/themes/romanticPurple.js +++ b/simple-mind-map/src/themes/romanticPurple.js @@ -1,53 +1,53 @@ -import defaultTheme from './default'; -import merge from 'deepmerge'; +import defaultTheme from './default' +import merge from 'deepmerge' -/** - * @Author: 王林 - * @Date: 2021-04-11 15:22:18 +/** + * @Author: 王林 + * @Date: 2021-04-11 15:22:18 * @Desc: 浪漫紫 */ export default merge(defaultTheme, { - // 连线的颜色 - lineColor: 'rgb(123, 115, 191)', - // 背景颜色 - backgroundColor: 'rgb(251, 251, 251)', - // 概要连线的粗细 - generalizationLineWidth: 1, - // 概要连线的颜色 - generalizationLineColor: '#333', - // 根节点样式 - root: { - fillColor: 'rgb(123, 115, 191)', - active: { - borderColor: 'rgb(61, 57, 96)' - } - }, - // 二级节点样式 - second: { - fillColor: 'rgb(239, 238, 246)', - color: '#333', - borderColor: 'rgb(123, 115, 191)', - borderWidth: 1, - fontSize: 14, - active: { - borderColor: 'rgb(61, 57, 96)' - } - }, - // 三级及以下节点样式 - node: { - fontSize: 12, - color: '#333', - active: { - borderColor: 'rgb(61, 57, 96)' - } - }, - // 概要节点样式 - generalization: { - fillColor: '#fff', - borderColor: '#333', - color: '#333', - active: { - borderColor: 'rgb(61, 57, 96)' - } + // 连线的颜色 + lineColor: 'rgb(123, 115, 191)', + // 背景颜色 + backgroundColor: 'rgb(251, 251, 251)', + // 概要连线的粗细 + generalizationLineWidth: 1, + // 概要连线的颜色 + generalizationLineColor: '#333', + // 根节点样式 + root: { + fillColor: 'rgb(123, 115, 191)', + active: { + borderColor: 'rgb(61, 57, 96)' } -}) \ No newline at end of file + }, + // 二级节点样式 + second: { + fillColor: 'rgb(239, 238, 246)', + color: '#333', + borderColor: 'rgb(123, 115, 191)', + borderWidth: 1, + fontSize: 14, + active: { + borderColor: 'rgb(61, 57, 96)' + } + }, + // 三级及以下节点样式 + node: { + fontSize: 12, + color: '#333', + active: { + borderColor: 'rgb(61, 57, 96)' + } + }, + // 概要节点样式 + generalization: { + fillColor: '#fff', + borderColor: '#333', + color: '#333', + active: { + borderColor: 'rgb(61, 57, 96)' + } + } +}) diff --git a/simple-mind-map/src/themes/skyGreen.js b/simple-mind-map/src/themes/skyGreen.js index bbc4ff88..57dcfcdb 100644 --- a/simple-mind-map/src/themes/skyGreen.js +++ b/simple-mind-map/src/themes/skyGreen.js @@ -1,59 +1,59 @@ -import defaultTheme from './default'; -import merge from 'deepmerge'; +import defaultTheme from './default' +import merge from 'deepmerge' -/** - * @Author: 王林 - * @Date: 2021-04-11 15:22:18 +/** + * @Author: 王林 + * @Date: 2021-04-11 15:22:18 * @Desc: 天清绿 */ export default merge(defaultTheme, { - // 连线的颜色 - lineColor: '#fff', - lineWidth: 3, - // 概要连线的粗细 - generalizationLineWidth: 3, - // 概要连线的颜色 - generalizationLineColor: '#fff', - // 背景颜色 - backgroundColor: 'rgb(80, 156, 170)', - // 根节点样式 - root: { - fillColor: '#fff', - borderColor: '', - borderWidth: 0, - color: 'rgb(65, 89, 158)', - active: { - borderColor: 'rgb(251, 227, 188)', - borderWidth: 3, - } - }, - // 二级节点样式 - second: { - fillColor: 'rgb(251, 227, 188)', - color: 'rgb(65, 89, 158)', - borderColor: '', - borderWidth: 0, - fontSize: 14, - active: { - borderColor: '#fff', - borderWidth: 2, - } - }, - // 三级及以下节点样式 - node: { - fontSize: 12, - color: 'rgb(65, 89, 158)', - active: { - borderColor: 'rgb(251, 227, 188)' - } - }, - // 概要节点样式 - generalization: { - fillColor: '#fff', - borderColor: 'transparent', - color: 'rgb(65, 89, 158)', - active: { - borderColor: 'rgb(251, 227, 188)' - } + // 连线的颜色 + lineColor: '#fff', + lineWidth: 3, + // 概要连线的粗细 + generalizationLineWidth: 3, + // 概要连线的颜色 + generalizationLineColor: '#fff', + // 背景颜色 + backgroundColor: 'rgb(80, 156, 170)', + // 根节点样式 + root: { + fillColor: '#fff', + borderColor: '', + borderWidth: 0, + color: 'rgb(65, 89, 158)', + active: { + borderColor: 'rgb(251, 227, 188)', + borderWidth: 3 } -}) \ No newline at end of file + }, + // 二级节点样式 + second: { + fillColor: 'rgb(251, 227, 188)', + color: 'rgb(65, 89, 158)', + borderColor: '', + borderWidth: 0, + fontSize: 14, + active: { + borderColor: '#fff', + borderWidth: 2 + } + }, + // 三级及以下节点样式 + node: { + fontSize: 12, + color: 'rgb(65, 89, 158)', + active: { + borderColor: 'rgb(251, 227, 188)' + } + }, + // 概要节点样式 + generalization: { + fillColor: '#fff', + borderColor: 'transparent', + color: 'rgb(65, 89, 158)', + active: { + borderColor: 'rgb(251, 227, 188)' + } + } +}) diff --git a/simple-mind-map/src/themes/vitalityOrange.js b/simple-mind-map/src/themes/vitalityOrange.js index 89651ebc..30ca2487 100644 --- a/simple-mind-map/src/themes/vitalityOrange.js +++ b/simple-mind-map/src/themes/vitalityOrange.js @@ -1,59 +1,59 @@ -import defaultTheme from './default'; -import merge from 'deepmerge'; +import defaultTheme from './default' +import merge from 'deepmerge' -/** - * @Author: 王林 - * @Date: 2021-04-11 15:22:18 +/** + * @Author: 王林 + * @Date: 2021-04-11 15:22:18 * @Desc: 活力橙 */ export default merge(defaultTheme, { - // 连线的颜色 - lineColor: 'rgb(254, 146, 0)', - lineWidth: 3, - // 概要连线的粗细 - generalizationLineWidth: 3, - // 概要连线的颜色 - generalizationLineColor: 'rgb(255, 222, 69)', - // 背景颜色 - backgroundColor: 'rgb(255, 246, 243)', - // 根节点样式 - root: { - fillColor: 'rgb(255, 112, 52)', - color: '#fff', - borderColor: '', - borderWidth: 0, - active: { - borderColor: 'rgb(51, 51, 51)', - borderWidth: 3, - } - }, - // 二级节点样式 - second: { - fillColor: '#fff', - color: 'rgb(51, 51, 51)', - borderColor: '', - borderWidth: 0, - fontSize: 14, - active: { - borderColor: 'rgb(255, 112, 52)', - borderWidth: 2 - } - }, - // 三级及以下节点样式 - node: { - fontSize: 12, - color: '#222', - active: { - borderColor: 'rgb(255, 112, 52)' - } - }, - // 概要节点样式 - generalization: { - fillColor: 'rgb(255, 222, 69)', - borderColor: 'transparent', - color: 'rgb(51, 51, 51)', - active: { - borderColor: 'rgb(255, 112, 52)' - } + // 连线的颜色 + lineColor: 'rgb(254, 146, 0)', + lineWidth: 3, + // 概要连线的粗细 + generalizationLineWidth: 3, + // 概要连线的颜色 + generalizationLineColor: 'rgb(255, 222, 69)', + // 背景颜色 + backgroundColor: 'rgb(255, 246, 243)', + // 根节点样式 + root: { + fillColor: 'rgb(255, 112, 52)', + color: '#fff', + borderColor: '', + borderWidth: 0, + active: { + borderColor: 'rgb(51, 51, 51)', + borderWidth: 3 } -}) \ No newline at end of file + }, + // 二级节点样式 + second: { + fillColor: '#fff', + color: 'rgb(51, 51, 51)', + borderColor: '', + borderWidth: 0, + fontSize: 14, + active: { + borderColor: 'rgb(255, 112, 52)', + borderWidth: 2 + } + }, + // 三级及以下节点样式 + node: { + fontSize: 12, + color: '#222', + active: { + borderColor: 'rgb(255, 112, 52)' + } + }, + // 概要节点样式 + generalization: { + fillColor: 'rgb(255, 222, 69)', + borderColor: 'transparent', + color: 'rgb(51, 51, 51)', + active: { + borderColor: 'rgb(255, 112, 52)' + } + } +}) diff --git a/simple-mind-map/src/utils/constant.js b/simple-mind-map/src/utils/constant.js index 7549a5d9..b3c84e07 100644 --- a/simple-mind-map/src/utils/constant.js +++ b/simple-mind-map/src/utils/constant.js @@ -1,175 +1,180 @@ -/** - * @Author: 王林 - * @Date: 2021-06-24 21:42:07 - * @Desc: 标签颜色列表 +/** + * @Author: 王林 + * @Date: 2021-06-24 21:42:07 + * @Desc: 标签颜色列表 */ export const tagColorList = [ - { - color: 'rgb(77, 65, 0)', - background: 'rgb(255, 244, 179)' - }, - { - color: 'rgb(0, 50, 77)', - background: 'rgb(179, 229, 255)' - }, - { - color: 'rgb(77, 0, 73)', - background: 'rgb(255, 179, 251)' - }, - { - color: 'rgb(57, 77, 0)', - background: 'rgb(236, 255, 179)' - }, - { - color: 'rgb(0, 77, 47)', - background: 'rgb(179, 255, 226)' - } + { + color: 'rgb(77, 65, 0)', + background: 'rgb(255, 244, 179)' + }, + { + color: 'rgb(0, 50, 77)', + background: 'rgb(179, 229, 255)' + }, + { + color: 'rgb(77, 0, 73)', + background: 'rgb(255, 179, 251)' + }, + { + color: 'rgb(57, 77, 0)', + background: 'rgb(236, 255, 179)' + }, + { + color: 'rgb(0, 77, 47)', + background: 'rgb(179, 255, 226)' + } ] -/** - * javascript comment - * @Author: 王林25 - * @Date: 2021-07-13 15:56:28 - * @Desc: 布局结构列表 +/** + * javascript comment + * @Author: 王林25 + * @Date: 2021-07-13 15:56:28 + * @Desc: 布局结构列表 */ export const layoutList = [ - { - name: '逻辑结构图', - value: 'logicalStructure', - img: require('../assets/logicalStructure.jpg') - }, - { - name: '思维导图', - value: 'mindMap', - img: require('../assets/mindMap.jpg') - }, - { - name: '组织结构图', - value: 'organizationStructure', - img: require('../assets/organizationStructure.jpg') - }, - { - name: '目录组织图', - value: 'catalogOrganization', - img: require('../assets/catalogOrganization.jpg') - } + { + name: '逻辑结构图', + value: 'logicalStructure', + img: require('../assets/logicalStructure.jpg') + }, + { + name: '思维导图', + value: 'mindMap', + img: require('../assets/mindMap.jpg') + }, + { + name: '组织结构图', + value: 'organizationStructure', + img: require('../assets/organizationStructure.jpg') + }, + { + name: '目录组织图', + value: 'catalogOrganization', + img: require('../assets/catalogOrganization.jpg') + } +] +export const layoutValueList = [ + 'logicalStructure', + 'mindMap', + 'catalogOrganization', + 'organizationStructure' ] -export const layoutValueList = ['logicalStructure', 'mindMap', 'catalogOrganization', 'organizationStructure'] -/** - * @Author: 王林 - * @Date: 2021-06-24 22:58:42 - * @Desc: 主题列表 +/** + * @Author: 王林 + * @Date: 2021-06-24 22:58:42 + * @Desc: 主题列表 */ export const themeList = [ - { - name: '默认', - value: 'default', - img: require('../assets/default.jpg') - }, - { - name: '脑图经典', - value: 'classic', - img: require('../assets/classic.jpg') - }, - { - name: '小黄人', - value: 'minions', - img: require('../assets/minions.jpg') - }, - { - name: '粉红葡萄', - value: 'pinkGrape', - img: require('../assets/pinkGrape.jpg') - }, - { - name: '薄荷', - value: 'mint', - img: require('../assets/mint.jpg') - }, - { - name: '金色vip', - value: 'gold', - img: require('../assets/gold.jpg') - }, - { - name: '活力橙', - value: 'vitalityOrange', - img: require('../assets/vitalityOrange.jpg') - }, - { - name: '绿叶', - value: 'greenLeaf', - img: require('../assets/greenLeaf.jpg') - }, - { - name: '暗色2', - value: 'dark2', - img: require('../assets/dark2.jpg') - }, - { - name: '天清绿', - value: 'skyGreen', - img: require('../assets/skyGreen.jpg') - }, - { - name: '脑图经典2', - value: 'classic2', - img: require('../assets/classic2.jpg') - }, - { - name: '脑图经典3', - value: 'classic3', - img: require('../assets/classic3.jpg') - }, - { - name: '脑图经典4', - value: 'classic4', - img: require('../assets/classic4.jpg') - }, - { - name: '经典绿', - value: 'classicGreen', - img: require('../assets/classicGreen.jpg') - }, - { - name: '经典蓝', - value: 'classicBlue', - img: require('../assets/classicBlue.jpg') - }, - { - name: '天空蓝', - value: 'blueSky', - img: require('../assets/blueSky.jpg') - }, - { - name: '脑残粉', - value: 'brainImpairedPink', - img: require('../assets/brainImpairedPink.jpg') - }, - { - name: '暗色', - value: 'dark', - img: require('../assets/dark.jpg') - }, - { - name: '泥土黄', - value: 'earthYellow', - img: require('../assets/earthYellow.jpg') - }, - { - name: '清新绿', - value: 'freshGreen', - img: require('../assets/freshGreen.jpg') - }, - { - name: '清新红', - value: 'freshRed', - img: require('../assets/freshRed.jpg') - }, - { - name: '浪漫紫', - value: 'romanticPurple', - img: require('../assets/romanticPurple.jpg') - } -] \ No newline at end of file + { + name: '默认', + value: 'default', + img: require('../assets/default.jpg') + }, + { + name: '脑图经典', + value: 'classic', + img: require('../assets/classic.jpg') + }, + { + name: '小黄人', + value: 'minions', + img: require('../assets/minions.jpg') + }, + { + name: '粉红葡萄', + value: 'pinkGrape', + img: require('../assets/pinkGrape.jpg') + }, + { + name: '薄荷', + value: 'mint', + img: require('../assets/mint.jpg') + }, + { + name: '金色vip', + value: 'gold', + img: require('../assets/gold.jpg') + }, + { + name: '活力橙', + value: 'vitalityOrange', + img: require('../assets/vitalityOrange.jpg') + }, + { + name: '绿叶', + value: 'greenLeaf', + img: require('../assets/greenLeaf.jpg') + }, + { + name: '暗色2', + value: 'dark2', + img: require('../assets/dark2.jpg') + }, + { + name: '天清绿', + value: 'skyGreen', + img: require('../assets/skyGreen.jpg') + }, + { + name: '脑图经典2', + value: 'classic2', + img: require('../assets/classic2.jpg') + }, + { + name: '脑图经典3', + value: 'classic3', + img: require('../assets/classic3.jpg') + }, + { + name: '脑图经典4', + value: 'classic4', + img: require('../assets/classic4.jpg') + }, + { + name: '经典绿', + value: 'classicGreen', + img: require('../assets/classicGreen.jpg') + }, + { + name: '经典蓝', + value: 'classicBlue', + img: require('../assets/classicBlue.jpg') + }, + { + name: '天空蓝', + value: 'blueSky', + img: require('../assets/blueSky.jpg') + }, + { + name: '脑残粉', + value: 'brainImpairedPink', + img: require('../assets/brainImpairedPink.jpg') + }, + { + name: '暗色', + value: 'dark', + img: require('../assets/dark.jpg') + }, + { + name: '泥土黄', + value: 'earthYellow', + img: require('../assets/earthYellow.jpg') + }, + { + name: '清新绿', + value: 'freshGreen', + img: require('../assets/freshGreen.jpg') + }, + { + name: '清新红', + value: 'freshRed', + img: require('../assets/freshRed.jpg') + }, + { + name: '浪漫紫', + value: 'romanticPurple', + img: require('../assets/romanticPurple.jpg') + } +] diff --git a/simple-mind-map/src/utils/index.js b/simple-mind-map/src/utils/index.js index 67907f16..586f37d4 100644 --- a/simple-mind-map/src/utils/index.js +++ b/simple-mind-map/src/utils/index.js @@ -1,252 +1,279 @@ -/** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-06 14:13:17 - * @Desc: 深度优先遍历树 +/** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-06 14:13:17 + * @Desc: 深度优先遍历树 */ -export const walk = (root, parent, beforeCallback, afterCallback, isRoot, layerIndex = 0, index = 0) => { - let stop = false - if (beforeCallback) { - stop = beforeCallback(root, parent, isRoot, layerIndex, index) - } - if (!stop && root.children && root.children.length > 0) { - let _layerIndex = layerIndex + 1 - root.children.forEach((node, nodeIndex) => { - walk(node, root, beforeCallback, afterCallback, false, _layerIndex, nodeIndex) - }) - } - afterCallback && afterCallback(root, parent, isRoot, layerIndex, index) +export const walk = ( + root, + parent, + beforeCallback, + afterCallback, + isRoot, + layerIndex = 0, + index = 0 +) => { + let stop = false + if (beforeCallback) { + stop = beforeCallback(root, parent, isRoot, layerIndex, index) + } + if (!stop && root.children && root.children.length > 0) { + let _layerIndex = layerIndex + 1 + root.children.forEach((node, nodeIndex) => { + walk( + node, + root, + beforeCallback, + afterCallback, + false, + _layerIndex, + nodeIndex + ) + }) + } + afterCallback && afterCallback(root, parent, isRoot, layerIndex, index) } -/** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-07 18:47:20 - * @Desc: 广度优先遍历树 +/** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-07 18:47:20 + * @Desc: 广度优先遍历树 */ export const bfsWalk = (root, callback) => { - callback(root) - let stack = [root] - let isStop = false - while (stack.length) { - if (isStop) { - break - } - let cur = stack.shift() - if (cur.children && cur.children.length) { - cur.children.forEach((item) => { - stack.push(item) - if(callback(item) === 'stop') { - isStop = true - } - }) - } + callback(root) + let stack = [root] + let isStop = false + while (stack.length) { + if (isStop) { + break } + let cur = stack.shift() + if (cur.children && cur.children.length) { + cur.children.forEach(item => { + stack.push(item) + if (callback(item) === 'stop') { + isStop = true + } + }) + } + } } -/** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-09 10:44:54 - * @Desc: 缩放图片尺寸 +/** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-09 10:44:54 + * @Desc: 缩放图片尺寸 */ export const resizeImgSize = (width, height, maxWidth, maxHeight) => { - let nRatio = width / height - let arr = [] - if (maxWidth && maxHeight) { - if (width <= maxWidth && height <= maxHeight) { - arr = [width, height] - } else { - let mRatio = maxWidth / maxHeight - if (nRatio > mRatio) { // 固定高度 - arr = [nRatio * maxHeight, maxHeight] - } else { // 固定宽度 - arr = [maxWidth, maxWidth / nRatio] - } - } - } else if (maxWidth) { - if (width <= maxWidth) { - arr = [width, height] - } else { - arr = [maxWidth, maxWidth / nRatio] - } - } else if (maxHeight) { - if (height <= maxHeight) { - arr = [width, height] - } else { - arr = [nRatio * maxHeight, maxHeight] - } + let nRatio = width / height + let arr = [] + if (maxWidth && maxHeight) { + if (width <= maxWidth && height <= maxHeight) { + arr = [width, height] + } else { + let mRatio = maxWidth / maxHeight + if (nRatio > mRatio) { + // 固定高度 + arr = [nRatio * maxHeight, maxHeight] + } else { + // 固定宽度 + arr = [maxWidth, maxWidth / nRatio] + } } - return arr + } else if (maxWidth) { + if (width <= maxWidth) { + arr = [width, height] + } else { + arr = [maxWidth, maxWidth / nRatio] + } + } else if (maxHeight) { + if (height <= maxHeight) { + arr = [width, height] + } else { + arr = [nRatio * maxHeight, maxHeight] + } + } + return arr } -/** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-09 10:18:42 - * @Desc: 缩放图片 +/** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-09 10:18:42 + * @Desc: 缩放图片 */ export const resizeImg = (imgUrl, maxWidth, maxHeight) => { - return new Promise((resolve, reject) => { - let img = new Image() - img.src = imgUrl - img.onload = () => { - let arr = resizeImgSize(img.naturalWidth, img.naturalHeight, maxWidth, maxHeight) - resolve(arr) - } - img.onerror = (e) => { - reject(e) - } - }) -} - -/** - * @Author: 王林 - * @Date: 2021-05-04 12:26:56 - * @Desc: 从头html结构字符串里获取带换行符的字符串 - */ -export const getStrWithBrFromHtml = (str) => { - str = str.replace(/
/img, '\n') - let el = document.createElement('div') - el.innerHTML = str - str = el.textContent - return str; -} - -/** - * @Author: 王林 - * @Date: 2021-05-04 14:45:39 - * @Desc: 极简的深拷贝 - */ -export const simpleDeepClone = (data) => { - try { - return JSON.parse(JSON.stringify(data)) - } catch (error) { - return null + return new Promise((resolve, reject) => { + let img = new Image() + img.src = imgUrl + img.onload = () => { + let arr = resizeImgSize( + img.naturalWidth, + img.naturalHeight, + maxWidth, + maxHeight + ) + resolve(arr) } + img.onerror = e => { + reject(e) + } + }) } -/** - * @Author: 王林 - * @Date: 2021-05-04 14:40:11 - * @Desc: 复制渲染树数据 +/** + * @Author: 王林 + * @Date: 2021-05-04 12:26:56 + * @Desc: 从头html结构字符串里获取带换行符的字符串 + */ +export const getStrWithBrFromHtml = str => { + str = str.replace(/
/gim, '\n') + let el = document.createElement('div') + el.innerHTML = str + str = el.textContent + return str +} + +/** + * @Author: 王林 + * @Date: 2021-05-04 14:45:39 + * @Desc: 极简的深拷贝 + */ +export const simpleDeepClone = data => { + try { + return JSON.parse(JSON.stringify(data)) + } catch (error) { + return null + } +} + +/** + * @Author: 王林 + * @Date: 2021-05-04 14:40:11 + * @Desc: 复制渲染树数据 */ export const copyRenderTree = (tree, root) => { - tree.data = simpleDeepClone(root.data) - tree.children = [] - if (root.children && root.children.length > 0) { - root.children.forEach((item, index) => { - tree.children[index] = copyRenderTree({}, item) - }) - } - return tree; + tree.data = simpleDeepClone(root.data) + tree.children = [] + if (root.children && root.children.length > 0) { + root.children.forEach((item, index) => { + tree.children[index] = copyRenderTree({}, item) + }) + } + return tree } -/** - * @Author: 王林 - * @Date: 2021-05-04 14:40:11 - * @Desc: 复制节点树数据 +/** + * @Author: 王林 + * @Date: 2021-05-04 14:40:11 + * @Desc: 复制节点树数据 */ export const copyNodeTree = (tree, root, removeActiveState = false) => { - tree.data = simpleDeepClone(root.nodeData ? root.nodeData.data : root.data) - if (removeActiveState) { - tree.data.isActive = false - } - tree.children = [] - if (root.children && root.children.length > 0) { - root.children.forEach((item, index) => { - tree.children[index] = copyNodeTree({}, item, removeActiveState) - }) - } else if (root.nodeData && root.nodeData.children && root.nodeData.children.length > 0) { - root.nodeData.children.forEach((item, index) => { - tree.children[index] = copyNodeTree({}, item, removeActiveState) - }) - } - return tree; + tree.data = simpleDeepClone(root.nodeData ? root.nodeData.data : root.data) + if (removeActiveState) { + tree.data.isActive = false + } + tree.children = [] + if (root.children && root.children.length > 0) { + root.children.forEach((item, index) => { + tree.children[index] = copyNodeTree({}, item, removeActiveState) + }) + } else if ( + root.nodeData && + root.nodeData.children && + root.nodeData.children.length > 0 + ) { + root.nodeData.children.forEach((item, index) => { + tree.children[index] = copyNodeTree({}, item, removeActiveState) + }) + } + return tree } -/** - * @Author: 王林 - * @Date: 2021-07-04 09:08:43 - * @Desc: 图片转成dataURL +/** + * @Author: 王林 + * @Date: 2021-07-04 09:08:43 + * @Desc: 图片转成dataURL */ -export const imgToDataUrl = (src) => { - return new Promise((resolve, reject) => { - const img = new Image() - // 跨域图片需要添加这个属性,否则画布被污染了无法导出图片 - img.setAttribute('crossOrigin', 'anonymous') - img.onload = () => { - try { - let canvas = document.createElement('canvas') - canvas.width = img.width - canvas.height = img.height - let ctx = canvas.getContext('2d') - // 图片绘制到canvas里 - ctx.drawImage(img, 0, 0, img.width, img.height) - resolve(canvas.toDataURL()) - } catch (e) { - reject(e) - } - } - img.onerror = (e) => { - reject(e) - } - img.src = src - }); +export const imgToDataUrl = src => { + return new Promise((resolve, reject) => { + const img = new Image() + // 跨域图片需要添加这个属性,否则画布被污染了无法导出图片 + img.setAttribute('crossOrigin', 'anonymous') + img.onload = () => { + try { + let canvas = document.createElement('canvas') + canvas.width = img.width + canvas.height = img.height + let ctx = canvas.getContext('2d') + // 图片绘制到canvas里 + ctx.drawImage(img, 0, 0, img.width, img.height) + resolve(canvas.toDataURL()) + } catch (e) { + reject(e) + } + } + img.onerror = e => { + reject(e) + } + img.src = src + }) } -/** - * @Author: 王林 - * @Date: 2021-07-04 16:20:06 - * @Desc: 下载文件 +/** + * @Author: 王林 + * @Date: 2021-07-04 16:20:06 + * @Desc: 下载文件 */ export const downloadFile = (file, fileName) => { - let a = document.createElement('a') - a.href = file - a.download = fileName - a.click() + let a = document.createElement('a') + a.href = file + a.download = fileName + a.click() } -/** - * @Author: 王林 - * @Date: 2021-07-11 10:36:47 - * @Desc: 节流函数 +/** + * @Author: 王林 + * @Date: 2021-07-11 10:36:47 + * @Desc: 节流函数 */ export const throttle = (fn, time = 300, ctx) => { - let timer = null - return () => { - if (timer) { - return - } - timer = setTimeout(() => { - fn.call(ctx) - timer = null - }, 300) - }; + let timer = null + return () => { + if (timer) { + return + } + timer = setTimeout(() => { + fn.call(ctx) + timer = null + }, time) + } } -/** - * javascript comment - * @Author: 王林25 - * @Date: 2021-07-12 10:27:36 - * @Desc: 异步执行任务队列 +/** + * javascript comment + * @Author: 王林25 + * @Date: 2021-07-12 10:27:36 + * @Desc: 异步执行任务队列 */ export const asyncRun = (taskList, callback = () => {}) => { - let index = 0 - let len = taskList.length - if (len <= 0) { - return callback() + let index = 0 + let len = taskList.length + if (len <= 0) { + return callback() + } + let loop = () => { + if (index >= len) { + callback() + return } - let loop = () => { - if (index >= len) { - callback() - return - } - taskList[index]() - setTimeout(() => { - index++ - loop() - }, 0) - } - loop() + taskList[index]() + setTimeout(() => { + index++ + loop() + }, 0) + } + loop() } diff --git a/simple-mind-map/src/utils/keyMap.js b/simple-mind-map/src/utils/keyMap.js index 3210e96f..5f8c20bc 100644 --- a/simple-mind-map/src/utils/keyMap.js +++ b/simple-mind-map/src/utils/keyMap.js @@ -1,69 +1,69 @@ const map = { - 'Backspace': 8, - 'Tab': 9, - 'Enter': 13, + Backspace: 8, + Tab: 9, + Enter: 13, - 'Shift': 16, - 'Control': 17, - 'Alt': 18, - 'CapsLock': 20, + Shift: 16, + Control: 17, + Alt: 18, + CapsLock: 20, - 'Esc': 27, + Esc: 27, - 'Spacebar': 32, + Spacebar: 32, - 'PageUp': 33, - 'PageDown': 34, - 'End': 35, - 'Home': 36, + PageUp: 33, + PageDown: 34, + End: 35, + Home: 36, - 'Insert': 45, + Insert: 45, - 'Left': 37, - 'Up': 38, - 'Right': 39, - 'Down': 40, + Left: 37, + Up: 38, + Right: 39, + Down: 40, - 'Del': 46, + Del: 46, - 'NumLock': 144, + NumLock: 144, - 'Cmd': 91, - 'CmdFF': 224, - 'F1': 112, - 'F2': 113, - 'F3': 114, - 'F4': 115, - 'F5': 116, - 'F6': 117, - 'F7': 118, - 'F8': 119, - 'F9': 120, - 'F10': 121, - 'F11': 122, - 'F12': 123, + Cmd: 91, + CmdFF: 224, + F1: 112, + F2: 113, + F3: 114, + F4: 115, + F5: 116, + F6: 117, + F7: 118, + F8: 119, + F9: 120, + F10: 121, + F11: 122, + F12: 123, - '`': 192, - '=': 187, - '-': 189, + '`': 192, + '=': 187, + '-': 189, - '/': 191, - '.': 190, + '/': 191, + '.': 190 } // 数字 for (let i = 0; i <= 9; i++) { - map[i] = i + 48 + map[i] = i + 48 } // 字母 'abcdefghijklmnopqrstuvwxyz'.split('').forEach((n, index) => { - map[n] = index + 65 + map[n] = index + 65 }) export const keyMap = map export const isKey = (e, key) => { - let code = typeof e === 'object' ? e.keyCode : e - return map[key] === code + let code = typeof e === 'object' ? e.keyCode : e + return map[key] === code } diff --git a/web/.prettierignore b/web/.prettierignore new file mode 100644 index 00000000..58bcc11e --- /dev/null +++ b/web/.prettierignore @@ -0,0 +1,9 @@ +src/assets +*/.DS_Store +node_modules +public +*.json +*.md +.eslintrc.js +.prettierignore +.prettierrc \ No newline at end of file diff --git a/web/.prettierrc b/web/.prettierrc new file mode 100644 index 00000000..ef93d948 --- /dev/null +++ b/web/.prettierrc @@ -0,0 +1,5 @@ +semi: false +singleQuote: true +printWidth: 80 +trailingComma: 'none' +arrowParens: 'avoid' diff --git a/web/package.json b/web/package.json index 2316b00a..fe58def5 100644 --- a/web/package.json +++ b/web/package.json @@ -6,7 +6,8 @@ "serve": "vue-cli-service serve", "build": "vue-cli-service build && node ../copy.js", "lint": "vue-cli-service lint", - "buildLibrary": "vue-cli-service build --target lib --name simpleMindMap ../simple-mind-map/index.js --dest ../simple-mind-map/dist" + "buildLibrary": "vue-cli-service build --target lib --name simpleMindMap ../simple-mind-map/index.js --dest ../simple-mind-map/dist", + "format": "prettier --write src/**" }, "dependencies": { "@toast-ui/editor": "^3.1.5", @@ -26,6 +27,7 @@ "eslint-plugin-vue": "^6.2.2", "less": "^3.12.2", "less-loader": "^7.1.0", + "prettier": "^1.19.1", "vue-template-compiler": "^2.6.11", "webpack": "^4.44.2" }, diff --git a/web/src/App.vue b/web/src/App.vue index 530b42d1..e2cf4e24 100644 --- a/web/src/App.vue +++ b/web/src/App.vue @@ -6,9 +6,9 @@ - - -
-

- - -

- -
-
+ .main .logo .sub-title { + margin-left: 0.5em; + font-size: 22px; + color: #fff; + background: linear-gradient(-45deg, #3967ff, #b500fe); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + } + + + +
+

+ + + +

+ +
+
    -
  • -
    导出
    -
    &#xe63e;
    -
  • - +
    导出
    +
    &#xe63e;
    + +
  • -
    另存为
    -
    &#xe657;
    -
  • - +
    另存为
    +
    &#xe657;
    + +
  • -
    export
    -
    &#xe642;
    -
  • - +
    export
    +
    &#xe642;
    + +
  • -
    打开
    -
    &#xebdf;
    -
  • - +
    打开
    +
    &#xebdf;
    + +
  • -
    新建
    -
    &#xe64e;
    -
  • - +
    新建
    +
    &#xe64e;
    + +
  • -
    剪切
    -
    &#xe601;
    -
  • - +
    剪切
    +
    &#xe601;
    + +
  • -
    整理
    -
    &#xe83b;
    -
  • - +
    整理
    +
    &#xe83b;
    + +
  • -
    复制
    -
    &#xe604;
    -
  • - +
    复制
    +
    &#xe604;
    + +
  • -
    粘贴
    -
    &#xe63f;
    -
  • - +
    粘贴
    +
    &#xe63f;
    + +
  • -
    上移
    -
    &#xe6be;
    -
  • - +
    上移
    +
    &#xe6be;
    + +
  • -
    下移
    -
    &#xe6bf;
    -
  • - +
    下移
    +
    &#xe6bf;
    + +
  • -
    概括总览
    -
    &#xe609;
    -
  • - +
    概括总览
    +
    &#xe609;
    + +
  • -
    全选
    -
    &#xf199;
    -
  • - +
    全选
    +
    &#xf199;
    + +
  • -
    导入
    -
    &#xe6a3;
    -
  • - +
    导入
    +
    &#xe6a3;
    + +
  • -
    后退-实
    -
    &#xe656;
    -
  • - +
    后退-实
    +
    &#xe656;
    + +
  • -
    前进
    -
    &#xe654;
    -
  • - +
    前进
    +
    &#xe654;
    + +
  • -
    撤回
    -
    &#xe603;
    -
  • - +
    撤回
    +
    &#xe603;
    + +
  • -
    前进
    -
    &#xe600;
    -
  • - +
    前进
    +
    &#xe600;
    + +
  • -
    恢复默认
    -
    &#xe60e;
    -
  • - +
    恢复默认
    +
    &#xe60e;
    + +
  • -
    换行
    -
    &#xe61e;
    -
  • - +
    换行
    +
    &#xe61e;
    + +
  • -
    缩小
    -
    &#xec13;
    -
  • - +
    缩小
    +
    &#xec13;
    + +
  • -
    编辑
    -
    &#xe626;
    -
  • - +
    编辑
    +
    &#xe626;
    + +
  • -
    放大
    -
    &#xe663;
    -
  • - +
    放大
    +
    &#xe663;
    + +
  • -
    全屏
    -
    &#xe664;
    -
  • - +
    全屏
    +
    &#xe664;
    + +
  • -
    定位
    -
    &#xe616;
    -
  • - +
    定位
    +
    &#xe616;
    + +
  • -
    导航
    -
    &#xe611;
    -
  • - +
    导航
    +
    &#xe611;
    + +
  • -
    键盘
    -
    &#xe64d;
    -
  • - +
    键盘
    +
    &#xe64d;
    + +
  • -
    全屏
    -
    &#xe602;
    -
  • - +
    全屏
    +
    &#xe602;
    + +
  • -
    导出
    -
    &#xe63d;
    -
  • - +
    导出
    +
    &#xe63d;
    + +
  • -
    标签
    -
    &#xe63c;
    -
  • - +
    标签
    +
    &#xe63c;
    + +
  • -
    流程-备注
    -
    &#xe65b;
    -
  • - +
    流程-备注
    +
    &#xe65b;
    + +
  • -
    超链接
    -
    &#xe6f4;
    -
  • - +
    超链接
    +
    &#xe6f4;
    + +
  • -
    主题
    -
    &#xe610;
    -
  • - +
    主题
    +
    &#xe610;
    + +
  • -
    笑脸
    -
    &#xe60f;
    -
  • - +
    笑脸
    +
    &#xe60f;
    + +
  • -
    图 片
    -
    &#xe629;
    -
  • - +
    图 片
    +
    &#xe629;
    + +
  • -
    结构
    -
    &#xe61d;
    -
  • - +
    结构
    +
    &#xe61d;
    + +
  • -
    样式
    -
    &#xe631;
    -
  • - +
    样式
    +
    &#xe631;
    + +
  • -
    符号-大纲树
    -
    &#xe71f;
    -
  • - +
    符号-大纲树
    +
    &#xe71f;
    + +
  • -
    添加子节点
    -
    &#xe622;
    -
  • - +
    添加子节点
    +
    &#xe622;
    + +
  • -
    节点
    -
    &#xe655;
    -
  • - +
    节点
    +
    &#xe655;
    + +
  • -
    删 除
    -
    &#xe696;
    -
  • - +
    删 除
    +
    &#xe696;
    + +
  • -
    HTSCIT_展开
    -
    &#xe64c;
    -
  • - +
    HTSCIT_展开
    +
    &#xe64c;
    + +
  • -
    HTSCIT_展开2
    -
    &#xe673;
    -
  • - +
    HTSCIT_展开2
    +
    &#xe673;
    +
-

Unicode 引用

-
+

Unicode 引用

+
-

Unicode 是字体在网页端最原始的应用方式,特点是:

-
    -
  • 支持按字体的方式去动态调整图标大小,颜色等等。
  • -
  • 默认情况下不支持多色,直接添加多色图标会自动去色。
  • -
-
-

注意:新版 iconfont 支持两种方式引用多色图标:SVG symbol 引用方式和彩色字体图标模式。(使用彩色字体图标需要在「编辑项目」中开启「彩色」选项后并重新生成。)

-
-

Unicode 使用步骤如下:

-

第一步:拷贝项目下面生成的 @font-face

-
Unicode 是字体在网页端最原始的应用方式,特点是:

+
    +
  • 支持按字体的方式去动态调整图标大小,颜色等等。
  • +
  • 默认情况下不支持多色,直接添加多色图标会自动去色。
  • +
+
+

+ 注意:新版 iconfont 支持两种方式引用多色图标:SVG symbol + 引用方式和彩色字体图标模式。(使用彩色字体图标需要在「编辑项目」中开启「彩色」选项后并重新生成。) +

+
+

Unicode 使用步骤如下:

+

+ 第一步:拷贝项目下面生成的 @font-face +

+
@font-face {
   font-family: 'iconfont';
   src: url('iconfont.woff2?t=1664005697217') format('woff2'),
@@ -335,8 +361,8 @@
        url('iconfont.ttf?t=1664005697217') format('truetype');
 }
 
-

第二步:定义使用 iconfont 的样式

-
第二步:定义使用 iconfont 的样式
+            
.iconfont {
   font-family: "iconfont" !important;
   font-size: 16px;
@@ -345,796 +371,773 @@
   -moz-osx-font-smoothing: grayscale;
 }
 
-

第三步:挑选相应图标并获取字体编码,应用于页面

-
+            

第三步:挑选相应图标并获取字体编码,应用于页面

+
 <span class="iconfont">&#x33;</span>
 
-
-

"iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。

-
+
+

+ "iconfont" 是你项目下的 + font-family。可以通过编辑项目查看,默认是 "iconfont"。 +

+
-
-
-
    - -
  • - -
    - 导出 -
    -
    .icondaochu1 -
    -
  • - -
  • - -
    - 另存为 -
    -
    .iconlingcunwei -
    -
  • - -
  • - -
    - export -
    -
    .iconexport -
    -
  • - -
  • - -
    - 打开 -
    -
    .icondakai -
    -
  • - -
  • - -
    - 新建 -
    -
    .iconxinjian -
    -
  • - -
  • - -
    - 剪切 -
    -
    .iconjianqie -
    -
  • - -
  • - -
    - 整理 -
    -
    .iconzhengli -
    -
  • - -
  • - -
    - 复制 -
    -
    .iconfuzhi -
    -
  • - -
  • - -
    - 粘贴 -
    -
    .iconniantie -
    -
  • - -
  • - -
    - 上移 -
    -
    .iconshangyi -
    -
  • - -
  • - -
    - 下移 -
    -
    .iconxiayi -
    -
  • - -
  • - -
    - 概括总览 -
    -
    .icongaikuozonglan -
    -
  • - -
  • - -
    - 全选 -
    -
    .iconquanxuan -
    -
  • - -
  • - -
    - 导入 -
    -
    .icondaoru -
    -
  • - -
  • - -
    - 后退-实 -
    -
    .iconhoutui-shi -
    -
  • - -
  • - -
    - 前进 -
    -
    .iconqianjin1 -
    -
  • - -
  • - -
    - 撤回 -
    -
    .iconwithdraw -
    -
  • - -
  • - -
    - 前进 -
    -
    .iconqianjin -
    -
  • - -
  • - -
    - 恢复默认 -
    -
    .iconhuifumoren -
    -
  • - -
  • - -
    - 换行 -
    -
    .iconhuanhang -
    -
  • - -
  • - -
    - 缩小 -
    -
    .iconsuoxiao -
    -
  • - -
  • - -
    - 编辑 -
    -
    .iconbianji -
    -
  • - -
  • - -
    - 放大 -
    -
    .iconfangda -
    -
  • - -
  • - -
    - 全屏 -
    -
    .iconquanping1 -
    -
  • - -
  • - -
    - 定位 -
    -
    .icondingwei -
    -
  • - -
  • - -
    - 导航 -
    -
    .icondaohang -
    -
  • - -
  • - -
    - 键盘 -
    -
    .iconjianpan -
    -
  • - -
  • - -
    - 全屏 -
    -
    .iconquanping -
    -
  • - -
  • - -
    - 导出 -
    -
    .icondaochu -
    -
  • - -
  • - -
    - 标签 -
    -
    .iconbiaoqian -
    -
  • - -
  • - -
    - 流程-备注 -
    -
    .iconflow-Mark -
    -
  • - -
  • - -
    - 超链接 -
    -
    .iconchaolianjie -
    -
  • - -
  • - -
    - 主题 -
    -
    .iconjingzi -
    -
  • - -
  • - -
    - 笑脸 -
    -
    .iconxiaolian -
    -
  • - -
  • - -
    - 图 片 -
    -
    .iconimage -
    -
  • - -
  • - -
    - 结构 -
    -
    .iconjiegou -
    -
  • - -
  • - -
    - 样式 -
    -
    .iconyangshi -
    -
  • - -
  • - -
    - 符号-大纲树 -
    -
    .iconfuhao-dagangshu -
    -
  • - -
  • - -
    - 添加子节点 -
    -
    .icontianjiazijiedian -
    -
  • - -
  • - -
    - 节点 -
    -
    .iconjiedian -
    -
  • - -
  • - -
    - 删 除 -
    -
    .iconshanchu -
    -
  • - -
  • - -
    - HTSCIT_展开 -
    -
    .iconzhankai -
    -
  • - -
  • - -
    - HTSCIT_展开2 -
    -
    .iconzhankai1 -
    -
  • - -
-
-

font-class 引用

-
- -

font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。

-

与 Unicode 使用方式相比,具有如下特点:

-
    -
  • 相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。
  • -
  • 因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。
  • -
-

使用步骤如下:

-

第一步:引入项目下面生成的 fontclass 代码:

-
<link rel="stylesheet" href="./iconfont.css">
-
-

第二步:挑选相应图标并获取类名,应用于页面:

-
<span class="iconfont iconxxx"></span>
-
-
-

" - iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。

-
-
-
-
+
+
    -
  • - -
    导出
    -
    #icondaochu1
    + +
    + 导出 +
    +
    .icondaochu1
  • - +
  • - -
    另存为
    -
    #iconlingcunwei
    + +
    + 另存为 +
    +
    .iconlingcunwei
  • - +
  • - -
    export
    -
    #iconexport
    + +
    + export +
    +
    .iconexport
  • - +
  • - -
    打开
    -
    #icondakai
    + +
    + 打开 +
    +
    .icondakai
  • - +
  • - -
    新建
    -
    #iconxinjian
    + +
    + 新建 +
    +
    .iconxinjian
  • - +
  • - -
    剪切
    -
    #iconjianqie
    + +
    + 剪切 +
    +
    .iconjianqie
  • - +
  • - -
    整理
    -
    #iconzhengli
    + +
    + 整理 +
    +
    .iconzhengli
  • - +
  • - -
    复制
    -
    #iconfuzhi
    + +
    + 复制 +
    +
    .iconfuzhi
  • - +
  • - -
    粘贴
    -
    #iconniantie
    + +
    + 粘贴 +
    +
    .iconniantie
  • - +
  • - -
    上移
    -
    #iconshangyi
    + +
    + 上移 +
    +
    .iconshangyi
  • - +
  • - -
    下移
    -
    #iconxiayi
    + +
    + 下移 +
    +
    .iconxiayi
  • - +
  • - -
    概括总览
    -
    #icongaikuozonglan
    + +
    + 概括总览 +
    +
    .icongaikuozonglan
  • - +
  • - -
    全选
    -
    #iconquanxuan
    + +
    + 全选 +
    +
    .iconquanxuan
  • - +
  • - -
    导入
    -
    #icondaoru
    + +
    + 导入 +
    +
    .icondaoru
  • - +
  • - -
    后退-实
    -
    #iconhoutui-shi
    + +
    + 后退-实 +
    +
    .iconhoutui-shi
  • - +
  • - -
    前进
    -
    #iconqianjin1
    + +
    + 前进 +
    +
    .iconqianjin1
  • - +
  • - -
    撤回
    -
    #iconwithdraw
    + +
    + 撤回 +
    +
    .iconwithdraw
  • - +
  • - -
    前进
    -
    #iconqianjin
    + +
    + 前进 +
    +
    .iconqianjin
  • - +
  • - -
    恢复默认
    -
    #iconhuifumoren
    + +
    + 恢复默认 +
    +
    .iconhuifumoren
  • - +
  • - -
    换行
    -
    #iconhuanhang
    + +
    + 换行 +
    +
    .iconhuanhang
  • - +
  • - -
    缩小
    -
    #iconsuoxiao
    + +
    + 缩小 +
    +
    .iconsuoxiao
  • - +
  • - -
    编辑
    -
    #iconbianji
    + +
    + 编辑 +
    +
    .iconbianji
  • - +
  • - -
    放大
    -
    #iconfangda
    + +
    + 放大 +
    +
    .iconfangda
  • - +
  • - -
    全屏
    -
    #iconquanping1
    + +
    + 全屏 +
    +
    .iconquanping1
  • - +
  • - -
    定位
    -
    #icondingwei
    + +
    + 定位 +
    +
    .icondingwei
  • - +
  • - -
    导航
    -
    #icondaohang
    + +
    + 导航 +
    +
    .icondaohang
  • - +
  • - -
    键盘
    -
    #iconjianpan
    + +
    + 键盘 +
    +
    .iconjianpan
  • - +
  • - -
    全屏
    -
    #iconquanping
    + +
    + 全屏 +
    +
    .iconquanping
  • - +
  • - -
    导出
    -
    #icondaochu
    + +
    + 导出 +
    +
    .icondaochu
  • - +
  • - -
    标签
    -
    #iconbiaoqian
    + +
    + 标签 +
    +
    .iconbiaoqian
  • - +
  • - -
    流程-备注
    -
    #iconflow-Mark
    + +
    + 流程-备注 +
    +
    .iconflow-Mark
  • - +
  • - -
    超链接
    -
    #iconchaolianjie
    + +
    + 超链接 +
    +
    .iconchaolianjie
  • - +
  • - -
    主题
    -
    #iconjingzi
    + +
    + 主题 +
    +
    .iconjingzi
  • - +
  • - -
    笑脸
    -
    #iconxiaolian
    + +
    + 笑脸 +
    +
    .iconxiaolian
  • - +
  • - -
    图 片
    -
    #iconimage
    + +
    + 图 片 +
    +
    .iconimage
  • - +
  • - -
    结构
    -
    #iconjiegou
    + +
    + 结构 +
    +
    .iconjiegou
  • - +
  • - -
    样式
    -
    #iconyangshi
    + +
    + 样式 +
    +
    .iconyangshi
  • - +
  • - -
    符号-大纲树
    -
    #iconfuhao-dagangshu
    + +
    + 符号-大纲树 +
    +
    .iconfuhao-dagangshu
  • - +
  • - -
    添加子节点
    -
    #icontianjiazijiedian
    + +
    + 添加子节点 +
    +
    .icontianjiazijiedian
  • - +
  • - -
    节点
    -
    #iconjiedian
    + +
    + 节点 +
    +
    .iconjiedian
  • - +
  • - -
    删 除
    -
    #iconshanchu
    + +
    + 删 除 +
    +
    .iconshanchu
  • - +
  • - -
    HTSCIT_展开
    -
    #iconzhankai
    + +
    + HTSCIT_展开 +
    +
    .iconzhankai
  • - +
  • - -
    HTSCIT_展开2
    -
    #iconzhankai1
    + +
    + HTSCIT_展开2 +
    +
    .iconzhankai1
  • -
-

Symbol 引用

-
+

font-class 引用

+
-

这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇文章 - 这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点:

-
    -
  • 支持多色图标了,不再受单色限制。
  • -
  • 通过一些技巧,支持像字体那样,通过 font-size, color 来调整样式。
  • -
  • 兼容性较差,支持 IE9+,及现代浏览器。
  • -
  • 浏览器渲染 SVG 的性能一般,还不如 png。
  • -
-

使用步骤如下:

-

第一步:引入项目下面生成的 symbol 代码:

-
<script src="./iconfont.js"></script>
+            

+ font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode + 书写不直观,语意不明确的问题。 +

+

与 Unicode 使用方式相比,具有如下特点:

+
    +
  • + 相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon + 是什么。 +
  • +
  • + 因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class + 里面的 Unicode 引用。 +
  • +
+

使用步骤如下:

+

+ 第一步:引入项目下面生成的 fontclass 代码: +

+
<link rel="stylesheet" href="./iconfont.css">
 
-

第二步:加入通用 CSS 代码(引入一次就行):

-
<style>
+            

第二步:挑选相应图标并获取类名,应用于页面:

+
<span class="iconfont iconxxx"></span>
+
+
+

+ " iconfont" 是你项目下的 + font-family。可以通过编辑项目查看,默认是 "iconfont"。 +

+
+
+
+
+
    +
  • + +
    导出
    +
    #icondaochu1
    +
  • + +
  • + +
    另存为
    +
    #iconlingcunwei
    +
  • + +
  • + +
    export
    +
    #iconexport
    +
  • + +
  • + +
    打开
    +
    #icondakai
    +
  • + +
  • + +
    新建
    +
    #iconxinjian
    +
  • + +
  • + +
    剪切
    +
    #iconjianqie
    +
  • + +
  • + +
    整理
    +
    #iconzhengli
    +
  • + +
  • + +
    复制
    +
    #iconfuzhi
    +
  • + +
  • + +
    粘贴
    +
    #iconniantie
    +
  • + +
  • + +
    上移
    +
    #iconshangyi
    +
  • + +
  • + +
    下移
    +
    #iconxiayi
    +
  • + +
  • + +
    概括总览
    +
    #icongaikuozonglan
    +
  • + +
  • + +
    全选
    +
    #iconquanxuan
    +
  • + +
  • + +
    导入
    +
    #icondaoru
    +
  • + +
  • + +
    后退-实
    +
    #iconhoutui-shi
    +
  • + +
  • + +
    前进
    +
    #iconqianjin1
    +
  • + +
  • + +
    撤回
    +
    #iconwithdraw
    +
  • + +
  • + +
    前进
    +
    #iconqianjin
    +
  • + +
  • + +
    恢复默认
    +
    #iconhuifumoren
    +
  • + +
  • + +
    换行
    +
    #iconhuanhang
    +
  • + +
  • + +
    缩小
    +
    #iconsuoxiao
    +
  • + +
  • + +
    编辑
    +
    #iconbianji
    +
  • + +
  • + +
    放大
    +
    #iconfangda
    +
  • + +
  • + +
    全屏
    +
    #iconquanping1
    +
  • + +
  • + +
    定位
    +
    #icondingwei
    +
  • + +
  • + +
    导航
    +
    #icondaohang
    +
  • + +
  • + +
    键盘
    +
    #iconjianpan
    +
  • + +
  • + +
    全屏
    +
    #iconquanping
    +
  • + +
  • + +
    导出
    +
    #icondaochu
    +
  • + +
  • + +
    标签
    +
    #iconbiaoqian
    +
  • + +
  • + +
    流程-备注
    +
    #iconflow-Mark
    +
  • + +
  • + +
    超链接
    +
    #iconchaolianjie
    +
  • + +
  • + +
    主题
    +
    #iconjingzi
    +
  • + +
  • + +
    笑脸
    +
    #iconxiaolian
    +
  • + +
  • + +
    图 片
    +
    #iconimage
    +
  • + +
  • + +
    结构
    +
    #iconjiegou
    +
  • + +
  • + +
    样式
    +
    #iconyangshi
    +
  • + +
  • + +
    符号-大纲树
    +
    #iconfuhao-dagangshu
    +
  • + +
  • + +
    添加子节点
    +
    #icontianjiazijiedian
    +
  • + +
  • + +
    节点
    +
    #iconjiedian
    +
  • + +
  • + +
    删 除
    +
    #iconshanchu
    +
  • + +
  • + +
    HTSCIT_展开
    +
    #iconzhankai
    +
  • + +
  • + +
    HTSCIT_展开2
    +
    #iconzhankai1
    +
  • +
+
+

Symbol 引用

+
+ +

+ 这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇文章 + 这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点: +

+
    +
  • 支持多色图标了,不再受单色限制。
  • +
  • + 通过一些技巧,支持像字体那样,通过 font-size, + color 来调整样式。 +
  • +
  • 兼容性较差,支持 IE9+,及现代浏览器。
  • +
  • 浏览器渲染 SVG 的性能一般,还不如 png。
  • +
+

使用步骤如下:

+

第一步:引入项目下面生成的 symbol 代码:

+
<script src="./iconfont.js"></script>
+
+

第二步:加入通用 CSS 代码(引入一次就行):

+
<style>
 .icon {
   width: 1em;
   height: 1em;
@@ -1144,34 +1147,36 @@
 }
 </style>
 
-

第三步:挑选相应图标并获取类名,应用于页面:

-
<svg class="icon" aria-hidden="true">
+            

第三步:挑选相应图标并获取类名,应用于页面:

+
<svg class="icon" aria-hidden="true">
   <use xlink:href="#icon-xxx"></use>
 </svg>
 
+
-
-
- - + + diff --git a/web/src/assets/icon-font/iconfont.css b/web/src/assets/icon-font/iconfont.css index 14583b1b..4461587d 100644 --- a/web/src/assets/icon-font/iconfont.css +++ b/web/src/assets/icon-font/iconfont.css @@ -1,12 +1,12 @@ @font-face { - font-family: "iconfont"; /* Project id 2479351 */ + font-family: 'iconfont'; /* Project id 2479351 */ src: url('iconfont.woff2?t=1664005697217') format('woff2'), - url('iconfont.woff?t=1664005697217') format('woff'), - url('iconfont.ttf?t=1664005697217') format('truetype'); + url('iconfont.woff?t=1664005697217') format('woff'), + url('iconfont.ttf?t=1664005697217') format('truetype'); } .iconfont { - font-family: "iconfont" !important; + font-family: 'iconfont' !important; font-size: 16px; font-style: normal; -webkit-font-smoothing: antialiased; @@ -14,174 +14,173 @@ } .icondaochu1:before { - content: "\e63e"; + content: '\e63e'; } .iconlingcunwei:before { - content: "\e657"; + content: '\e657'; } .iconexport:before { - content: "\e642"; + content: '\e642'; } .icondakai:before { - content: "\ebdf"; + content: '\ebdf'; } .iconxinjian:before { - content: "\e64e"; + content: '\e64e'; } .iconjianqie:before { - content: "\e601"; + content: '\e601'; } .iconzhengli:before { - content: "\e83b"; + content: '\e83b'; } .iconfuzhi:before { - content: "\e604"; + content: '\e604'; } .iconniantie:before { - content: "\e63f"; + content: '\e63f'; } .iconshangyi:before { - content: "\e6be"; + content: '\e6be'; } .iconxiayi:before { - content: "\e6bf"; + content: '\e6bf'; } .icongaikuozonglan:before { - content: "\e609"; + content: '\e609'; } .iconquanxuan:before { - content: "\f199"; + content: '\f199'; } .icondaoru:before { - content: "\e6a3"; + content: '\e6a3'; } .iconhoutui-shi:before { - content: "\e656"; + content: '\e656'; } .iconqianjin1:before { - content: "\e654"; + content: '\e654'; } .iconwithdraw:before { - content: "\e603"; + content: '\e603'; } .iconqianjin:before { - content: "\e600"; + content: '\e600'; } .iconhuifumoren:before { - content: "\e60e"; + content: '\e60e'; } .iconhuanhang:before { - content: "\e61e"; + content: '\e61e'; } .iconsuoxiao:before { - content: "\ec13"; + content: '\ec13'; } .iconbianji:before { - content: "\e626"; + content: '\e626'; } .iconfangda:before { - content: "\e663"; + content: '\e663'; } .iconquanping1:before { - content: "\e664"; + content: '\e664'; } .icondingwei:before { - content: "\e616"; + content: '\e616'; } .icondaohang:before { - content: "\e611"; + content: '\e611'; } .iconjianpan:before { - content: "\e64d"; + content: '\e64d'; } .iconquanping:before { - content: "\e602"; + content: '\e602'; } .icondaochu:before { - content: "\e63d"; + content: '\e63d'; } .iconbiaoqian:before { - content: "\e63c"; + content: '\e63c'; } .iconflow-Mark:before { - content: "\e65b"; + content: '\e65b'; } .iconchaolianjie:before { - content: "\e6f4"; + content: '\e6f4'; } .iconjingzi:before { - content: "\e610"; + content: '\e610'; } .iconxiaolian:before { - content: "\e60f"; + content: '\e60f'; } .iconimage:before { - content: "\e629"; + content: '\e629'; } .iconjiegou:before { - content: "\e61d"; + content: '\e61d'; } .iconyangshi:before { - content: "\e631"; + content: '\e631'; } .iconfuhao-dagangshu:before { - content: "\e71f"; + content: '\e71f'; } .icontianjiazijiedian:before { - content: "\e622"; + content: '\e622'; } .iconjiedian:before { - content: "\e655"; + content: '\e655'; } .iconshanchu:before { - content: "\e696"; + content: '\e696'; } .iconzhankai:before { - content: "\e64c"; + content: '\e64c'; } .iconzhankai1:before { - content: "\e673"; + content: '\e673'; } - diff --git a/web/src/assets/icon-font/iconfont.js b/web/src/assets/icon-font/iconfont.js index 178e4b0a..894d6ff8 100644 --- a/web/src/assets/icon-font/iconfont.js +++ b/web/src/assets/icon-font/iconfont.js @@ -1 +1,68 @@ -window._iconfont_svg_string_2479351='',function(l){var c=(c=document.getElementsByTagName("script"))[c.length-1],a=c.getAttribute("data-injectcss"),c=c.getAttribute("data-disable-injectsvg");if(!c){var h,t,i,o,s,z=function(c,a){a.parentNode.insertBefore(c,a)};if(a&&!l.__iconfont__svg__cssinject__){l.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(c){console&&console.log(c)}}h=function(){var c,a=document.createElement("div");a.innerHTML=l._iconfont_svg_string_2479351,(a=a.getElementsByTagName("svg")[0])&&(a.setAttribute("aria-hidden","true"),a.style.position="absolute",a.style.width=0,a.style.height=0,a.style.overflow="hidden",a=a,(c=document.body).firstChild?z(a,c.firstChild):c.appendChild(a))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(h,0):(t=function(){document.removeEventListener("DOMContentLoaded",t,!1),h()},document.addEventListener("DOMContentLoaded",t,!1)):document.attachEvent&&(i=h,o=l.document,s=!1,d(),o.onreadystatechange=function(){"complete"==o.readyState&&(o.onreadystatechange=null,v())})}function v(){s||(s=!0,i())}function d(){try{o.documentElement.doScroll("left")}catch(c){return void setTimeout(d,50)}v()}}(window); \ No newline at end of file +(window._iconfont_svg_string_2479351 = + ''), + (function(l) { + var c = (c = document.getElementsByTagName('script'))[c.length - 1], + a = c.getAttribute('data-injectcss'), + c = c.getAttribute('data-disable-injectsvg') + if (!c) { + var h, + t, + i, + o, + s, + z = function(c, a) { + a.parentNode.insertBefore(c, a) + } + if (a && !l.__iconfont__svg__cssinject__) { + l.__iconfont__svg__cssinject__ = !0 + try { + document.write( + '' + ) + } catch (c) { + console && console.log(c) + } + } + (h = function() { + var c, + a = document.createElement('div') + ;(a.innerHTML = l._iconfont_svg_string_2479351), + (a = a.getElementsByTagName('svg')[0]) && + (a.setAttribute('aria-hidden', 'true'), + (a.style.position = 'absolute'), + (a.style.width = 0), + (a.style.height = 0), + (a.style.overflow = 'hidden'), + (a = a), + (c = document.body).firstChild + ? z(a, c.firstChild) + : c.appendChild(a)) + }), + document.addEventListener + ? ~['complete', 'loaded', 'interactive'].indexOf(document.readyState) + ? setTimeout(h, 0) + : ((t = function() { + document.removeEventListener('DOMContentLoaded', t, !1), h() + }), + document.addEventListener('DOMContentLoaded', t, !1)) + : document.attachEvent && + ((i = h), + (o = l.document), + (s = !1), + d(), + (o.onreadystatechange = function() { + 'complete' == o.readyState && ((o.onreadystatechange = null), v()) + })) + } + function v() { + s || ((s = !0), i()) + } + function d() { + try { + o.documentElement.doScroll('left') + } catch (c) { + return void setTimeout(d, 50) + } + v() + } + })(window) diff --git a/web/src/components/ImgUpload/index.vue b/web/src/components/ImgUpload/index.vue index c27e11b3..ea1a5122 100644 --- a/web/src/components/ImgUpload/index.vue +++ b/web/src/components/ImgUpload/index.vue @@ -30,21 +30,21 @@ diff --git a/web/src/components/ImgUpload/style.less b/web/src/components/ImgUpload/style.less index 239ba37d..bd7f8b60 100644 --- a/web/src/components/ImgUpload/style.less +++ b/web/src/components/ImgUpload/style.less @@ -1,80 +1,80 @@ .imgUploadContainer { + width: 100%; + height: 100%; + display: flex; + justify-content: center; + align-items: center; + background-color: rgba(255, 255, 255, 0.9); + z-index: 1000; + + .imgUploadPanel { + position: relative; width: 100%; - height: 100%; - display: flex; - justify-content: center; - align-items: center; - background-color: rgba(255,255,255,.9); - z-index: 1000; + font-size: 22px; + white-space: nowrap; + color: #909090; + cursor: default; + user-select: none; - .imgUploadPanel { - position: relative; - width: 100%; - font-size: 22px; - white-space: nowrap; - color: #909090; - cursor: default; - user-select: none; - - .title { - margin-bottom: 15px; - font-size: 22px; - font-weight: 700; - color: hsla(218,9%,51%,.8); - } - - .closeBtn { - position: absolute; - right: 25px; - top: 32px; - cursor: pointer; - } - - .imgUploadInputArea { - display: block; - width: 100%; - height: 200px; - font-size: 20px; - color: rgba(51,51,51,.4); - background-color: hsla(0,0%,87%,.6); - border: none; - outline: none; - cursor: pointer; - text-align: center; - display: flex; - justify-content: center; - align-items: center; - white-space: normal; - padding: 10px; - } - - #imgUploadInput { - display: none; - } - - .uploadInfoBox { - position: relative; - width: 100%; - height: 200px; - background-color: hsla(0,0%,87%,.6); - - .previewBox { - width: 100%; - height: 100%; - background-size: contain; - background-repeat: no-repeat; - background-position: center; - } - - .delBtn { - position: absolute; - right: 0px; - top: 0px; - cursor: pointer; - width: 20px; - height: 20px; - background-color: #fff; - } - } + .title { + margin-bottom: 15px; + font-size: 22px; + font-weight: 700; + color: hsla(218, 9%, 51%, 0.8); } -} \ No newline at end of file + + .closeBtn { + position: absolute; + right: 25px; + top: 32px; + cursor: pointer; + } + + .imgUploadInputArea { + display: block; + width: 100%; + height: 200px; + font-size: 20px; + color: rgba(51, 51, 51, 0.4); + background-color: hsla(0, 0%, 87%, 0.6); + border: none; + outline: none; + cursor: pointer; + text-align: center; + display: flex; + justify-content: center; + align-items: center; + white-space: normal; + padding: 10px; + } + + #imgUploadInput { + display: none; + } + + .uploadInfoBox { + position: relative; + width: 100%; + height: 200px; + background-color: hsla(0, 0%, 87%, 0.6); + + .previewBox { + width: 100%; + height: 100%; + background-size: contain; + background-repeat: no-repeat; + background-position: center; + } + + .delBtn { + position: absolute; + right: 0px; + top: 0px; + cursor: pointer; + width: 20px; + height: 20px; + background-color: #fff; + } + } + } +} diff --git a/web/src/config/index.js b/web/src/config/index.js index 22e602b9..2045c316 100644 --- a/web/src/config/index.js +++ b/web/src/config/index.js @@ -1,46 +1,57 @@ // 字体列表 export const fontFamilyList = [ - { - name: '宋体', - value: '宋体, SimSun, Songti SC' - }, { - name: '微软雅黑', - value: '微软雅黑, Microsoft YaHei' - }, { - name: '楷体', - value: '楷体, 楷体_GB2312, SimKai, STKaiti' - }, { - name: '黑体', - value: '黑体, SimHei, Heiti SC' - }, { - name: '隶书', - value: '隶书, SimLi' - }, { - name: 'Andale Mono', - value: 'andale mono' - }, { - name: 'Arial', - value: 'arial, helvetica, sans-serif' - }, { - name: 'arialBlack', - value: 'arial black, avant garde' - }, { - name: 'Comic Sans Ms', - value: 'comic sans ms' - }, { - name: 'Impact', - value: 'impact, chicago' - }, { - name: 'Times New Roman', - value: 'times new roman' - }, { - name: 'Sans-Serif', - value: 'sans-serif' - }, - { - name: 'serif', - value: 'serif' - } + { + name: '宋体', + value: '宋体, SimSun, Songti SC' + }, + { + name: '微软雅黑', + value: '微软雅黑, Microsoft YaHei' + }, + { + name: '楷体', + value: '楷体, 楷体_GB2312, SimKai, STKaiti' + }, + { + name: '黑体', + value: '黑体, SimHei, Heiti SC' + }, + { + name: '隶书', + value: '隶书, SimLi' + }, + { + name: 'Andale Mono', + value: 'andale mono' + }, + { + name: 'Arial', + value: 'arial, helvetica, sans-serif' + }, + { + name: 'arialBlack', + value: 'arial black, avant garde' + }, + { + name: 'Comic Sans Ms', + value: 'comic sans ms' + }, + { + name: 'Impact', + value: 'impact, chicago' + }, + { + name: 'Times New Roman', + value: 'times new roman' + }, + { + name: 'Sans-Serif', + value: 'sans-serif' + }, + { + name: 'serif', + value: 'serif' + } ] // 字号 @@ -51,42 +62,42 @@ export const lineHeightList = [1, 1.5, 2, 2.5, 3] // 颜色 export const colorList = [ - '#4D4D4D', - '#999999', - '#FFFFFF', - '#F44E3B', - '#FE9200', - '#FCDC00', - '#DBDF00', - '#A4DD00', - '#68CCCA', - '#73D8FF', - '#AEA1FF', - '#FDA1FF', - '#333333', - '#808080', - '#cccccc', - '#D33115', - '#E27300', - '#FCC400', - '#B0BC00', - '#68BC00', - '#16A5A5', - '#009CE0', - '#7B64FF', - '#FA28FF', - '#000000', - '#666666', - '#B3B3B3', - '#9F0500', - '#C45100', - '#FB9E00', - '#808900', - '#194D33', - '#0C797D', - '#0062B1', - '#653294', - '#AB149E' + '#4D4D4D', + '#999999', + '#FFFFFF', + '#F44E3B', + '#FE9200', + '#FCDC00', + '#DBDF00', + '#A4DD00', + '#68CCCA', + '#73D8FF', + '#AEA1FF', + '#FDA1FF', + '#333333', + '#808080', + '#cccccc', + '#D33115', + '#E27300', + '#FCC400', + '#B0BC00', + '#68BC00', + '#16A5A5', + '#009CE0', + '#7B64FF', + '#FA28FF', + '#000000', + '#666666', + '#B3B3B3', + '#9F0500', + '#C45100', + '#FB9E00', + '#808900', + '#194D33', + '#0C797D', + '#0062B1', + '#653294', + '#AB149E' ] // 边框宽度 @@ -94,34 +105,34 @@ export const borderWidthList = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] // 边框样式 export const borderDasharrayList = [ - { - name: '实线', - value: 'none' - }, - { - name: '虚线1', - value: '5,5' - }, - { - name: '虚线2', - value: '10,10' - }, - { - name: '虚线3', - value: '20,10,5,5,5,10' - }, - { - name: '虚线4', - value: '5, 5, 1, 5' - }, - { - name: '虚线5', - value: '15, 10, 5, 10, 15' - }, - { - name: '虚线6', - value: '1, 5' - } + { + name: '实线', + value: 'none' + }, + { + name: '虚线1', + value: '5,5' + }, + { + name: '虚线2', + value: '10,10' + }, + { + name: '虚线3', + value: '20,10,5,5,5,10' + }, + { + name: '虚线4', + value: '5, 5, 1, 5' + }, + { + name: '虚线5', + value: '15, 10, 5, 10, 15' + }, + { + name: '虚线6', + value: '1, 5' + } ] // 圆角 @@ -132,239 +143,239 @@ export const lineWidthList = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] // 连线风格 export const lineStyleList = [ - { - name: '直线', - value: 'straight' - }, - { - name: '曲线', - value: 'curve' - }, - { - name: '直连', - value: 'direct' - } + { + name: '直线', + value: 'straight' + }, + { + name: '曲线', + value: 'curve' + }, + { + name: '直连', + value: 'direct' + } ] // 图片重复方式 export const backgroundRepeatList = [ - { - name: '不重复', - value: 'no-repeat' - }, - { - name: '重复', - value: 'repeat' - }, - { - name: '水平方向重复', - value: 'repeat-x' - }, - { - name: '垂直方向重复', - value: 'repeat-y' - } + { + name: '不重复', + value: 'no-repeat' + }, + { + name: '重复', + value: 'repeat' + }, + { + name: '水平方向重复', + value: 'repeat-x' + }, + { + name: '垂直方向重复', + value: 'repeat-y' + } ] // 背景图片定位 export const backgroundPositionList = [ - { - name: '默认', - value: '0% 0%' - }, - { - name: '左上', - value: 'left top' - }, - { - name: '左中', - value: 'left center' - }, - { - name: '左下', - value: 'left bottom' - }, - { - name: '右上', - value: 'right top' - }, - { - name: '右中', - value: 'right center' - }, - { - name: '右下', - value: 'right bottom' - }, - { - name: '中上', - value: 'center top' - }, - { - name: '居中', - value: 'center center' - }, - { - name: '中下', - value: 'center bottom' - } + { + name: '默认', + value: '0% 0%' + }, + { + name: '左上', + value: 'left top' + }, + { + name: '左中', + value: 'left center' + }, + { + name: '左下', + value: 'left bottom' + }, + { + name: '右上', + value: 'right top' + }, + { + name: '右中', + value: 'right center' + }, + { + name: '右下', + value: 'right bottom' + }, + { + name: '中上', + value: 'center top' + }, + { + name: '居中', + value: 'center center' + }, + { + name: '中下', + value: 'center bottom' + } ] // 数据存储 export const store = { - sidebarZIndex: 1//侧边栏zIndex + sidebarZIndex: 1 //侧边栏zIndex } // 快捷键列表 export const shortcutKeyList = [ - { - type: '节点操作', - list: [ - { - icon: 'icontianjiazijiedian', - name: '插入下级节点', - value: 'Tab' - }, - { - icon: 'iconjiedian', - name: '插入同级节点', - value: 'Enter' - }, - { - icon: 'iconshangyi', - name: '上移节点', - value: 'Ctrl + ↑' - }, - { - icon: 'iconxiayi', - name: '下移节点', - value: 'Ctrl + ↓' - }, - { - icon: 'icongaikuozonglan', - name: '插入概要', - value: 'Ctrl + S' - }, - { - icon: 'iconzhankai', - name: '展开/收起节点', - value: '/' - }, - { - icon: 'iconshanchu', - name: '删除节点', - value: 'Delete | Backspace' - }, - { - icon: 'iconfuzhi', - name: '复制节点', - value: 'Ctrl + C' - }, - { - icon: 'iconjianqie', - name: '剪切节点', - value: 'Ctrl + X' - }, - { - icon: 'iconniantie', - name: '粘贴节点', - value: 'Ctrl + V' - }, - { - icon: 'iconbianji', - name: '编辑节点', - value: 'F2' - }, - { - icon: 'iconhuanhang', - name: '文本换行', - value: 'Shift + Enter' - }, - { - icon: 'iconhoutui-shi', - name: '回退', - value: 'Ctrl + Z' - }, - { - icon: 'iconqianjin1', - name: '前进', - value: 'Ctrl + Y' - }, - { - icon: 'iconquanxuan', - name: '全选', - value: 'Ctrl + A' - }, - { - icon: 'iconquanxuan', - name: '多选', - value: '右键 / Ctrl + 左键' - }, - { - icon: 'iconzhengli', - name: '一键整理布局', - value: 'Ctrl + L' - }, - ] - }, - { - type: '画布操作', - list: [ - { - icon: 'iconfangda', - name: '放大', - value: 'Ctrl + +' - }, - { - icon: 'iconsuoxiao', - name: '缩小', - value: 'Ctrl + -' - }, - { - icon: 'icondingwei', - name: '恢复默认', - value: 'Ctrl + Enter' - } - ] - } + { + type: '节点操作', + list: [ + { + icon: 'icontianjiazijiedian', + name: '插入下级节点', + value: 'Tab' + }, + { + icon: 'iconjiedian', + name: '插入同级节点', + value: 'Enter' + }, + { + icon: 'iconshangyi', + name: '上移节点', + value: 'Ctrl + ↑' + }, + { + icon: 'iconxiayi', + name: '下移节点', + value: 'Ctrl + ↓' + }, + { + icon: 'icongaikuozonglan', + name: '插入概要', + value: 'Ctrl + S' + }, + { + icon: 'iconzhankai', + name: '展开/收起节点', + value: '/' + }, + { + icon: 'iconshanchu', + name: '删除节点', + value: 'Delete | Backspace' + }, + { + icon: 'iconfuzhi', + name: '复制节点', + value: 'Ctrl + C' + }, + { + icon: 'iconjianqie', + name: '剪切节点', + value: 'Ctrl + X' + }, + { + icon: 'iconniantie', + name: '粘贴节点', + value: 'Ctrl + V' + }, + { + icon: 'iconbianji', + name: '编辑节点', + value: 'F2' + }, + { + icon: 'iconhuanhang', + name: '文本换行', + value: 'Shift + Enter' + }, + { + icon: 'iconhoutui-shi', + name: '回退', + value: 'Ctrl + Z' + }, + { + icon: 'iconqianjin1', + name: '前进', + value: 'Ctrl + Y' + }, + { + icon: 'iconquanxuan', + name: '全选', + value: 'Ctrl + A' + }, + { + icon: 'iconquanxuan', + name: '多选', + value: '右键 / Ctrl + 左键' + }, + { + icon: 'iconzhengli', + name: '一键整理布局', + value: 'Ctrl + L' + } + ] + }, + { + type: '画布操作', + list: [ + { + icon: 'iconfangda', + name: '放大', + value: 'Ctrl + +' + }, + { + icon: 'iconsuoxiao', + name: '缩小', + value: 'Ctrl + -' + }, + { + icon: 'icondingwei', + name: '恢复默认', + value: 'Ctrl + Enter' + } + ] + } ] // 形状列表 export const shapeList = [ - { - name: '矩形', - value: 'rectangle' - }, - { - name: '菱形', - value: 'diamond' - }, - { - name: '平行四边形', - value: 'parallelogram' - }, - { - name: '圆角矩形', - value: 'roundedRectangle' - }, - { - name: '八角矩形', - value: 'octagonalRectangle' - }, - { - name: '外三角矩形', - value: 'outerTriangularRectangle' - }, - { - name: '内三角矩形', - value: 'innerTriangularRectangle' - }, - { - name: '椭圆', - value: 'ellipse' - }, - { - name: '圆', - value: 'circle' - } -] \ No newline at end of file + { + name: '矩形', + value: 'rectangle' + }, + { + name: '菱形', + value: 'diamond' + }, + { + name: '平行四边形', + value: 'parallelogram' + }, + { + name: '圆角矩形', + value: 'roundedRectangle' + }, + { + name: '八角矩形', + value: 'octagonalRectangle' + }, + { + name: '外三角矩形', + value: 'outerTriangularRectangle' + }, + { + name: '内三角矩形', + value: 'innerTriangularRectangle' + }, + { + name: '椭圆', + value: 'ellipse' + }, + { + name: '圆', + value: 'circle' + } +] diff --git a/web/src/pages/Edit/Index.vue b/web/src/pages/Edit/Index.vue index 969c976b..3691b8d3 100644 --- a/web/src/pages/Edit/Index.vue +++ b/web/src/pages/Edit/Index.vue @@ -8,34 +8,34 @@ \ No newline at end of file + diff --git a/web/src/pages/Edit/components/Fullscreen.vue b/web/src/pages/Edit/components/Fullscreen.vue index 23365234..a924ed75 100644 --- a/web/src/pages/Edit/components/Fullscreen.vue +++ b/web/src/pages/Edit/components/Fullscreen.vue @@ -7,7 +7,7 @@ diff --git a/web/src/pages/Edit/components/Navigator.vue b/web/src/pages/Edit/components/Navigator.vue index d9bad52b..ca962355 100644 --- a/web/src/pages/Edit/components/Navigator.vue +++ b/web/src/pages/Edit/components/Navigator.vue @@ -13,7 +13,7 @@ :style="{ transform: `scale(${svgBoxScale})`, left: svgBoxLeft + 'px', - top: svgBoxTop + 'px', + top: svgBoxTop + 'px' }" >
@@ -24,8 +24,8 @@ export default { props: { mindMap: { - type: Object, - }, + type: Object + } }, data() { return { @@ -40,47 +40,47 @@ export default { left: 0, top: 0, bottom: 0, - right: 0, - }, - }; + right: 0 + } + } }, mounted() { - this.$bus.$on("toggle_mini_map", this.toggle_mini_map); - this.$bus.$on("data_change", this.data_change); - this.$bus.$on("view_data_change", this.data_change); - this.$bus.$on("node_tree_render_end", this.data_change); + this.$bus.$on('toggle_mini_map', this.toggle_mini_map) + this.$bus.$on('data_change', this.data_change) + this.$bus.$on('view_data_change', this.data_change) + this.$bus.$on('node_tree_render_end', this.data_change) }, destroyed() { - this.$bus.$off("toggle_mini_map", this.toggle_mini_map); - this.$bus.$off("data_change", this.data_change); - this.$bus.$off("view_data_change", this.data_change); - this.$bus.$off("node_tree_render_end", this.data_change); + this.$bus.$off('toggle_mini_map', this.toggle_mini_map) + this.$bus.$off('data_change', this.data_change) + this.$bus.$off('view_data_change', this.data_change) + this.$bus.$off('node_tree_render_end', this.data_change) }, methods: { toggle_mini_map(show) { - this.showMiniMap = show; + this.showMiniMap = show this.$nextTick(() => { if (this.$refs.navigatorBox) { - this.init(); + this.init() } if (this.$refs.svgBox) { - this.drawMiniMap(); + this.drawMiniMap() } - }); + }) }, data_change() { if (!this.showMiniMap) { - return; + return } - clearTimeout(this.timer); + clearTimeout(this.timer) this.timer = setTimeout(() => { - this.drawMiniMap(); - }, 500); + this.drawMiniMap() + }, 500) }, init() { - let { width, height } = this.$refs.navigatorBox.getBoundingClientRect(); - this.boxWidth = width; - this.boxHeight = height; + let { width, height } = this.$refs.navigatorBox.getBoundingClientRect() + this.boxWidth = width + this.boxHeight = height }, drawMiniMap() { @@ -89,32 +89,29 @@ export default { viewBoxStyle, miniMapBoxScale, miniMapBoxLeft, - miniMapBoxTop, - } = this.mindMap.miniMap.calculationMiniMap( - this.boxWidth, - this.boxHeight - ); + miniMapBoxTop + } = this.mindMap.miniMap.calculationMiniMap(this.boxWidth, this.boxHeight) // 渲染到小地图 - this.$refs.svgBox.innerHTML = svgHTML; - this.viewBoxStyle = viewBoxStyle; - this.svgBoxScale = miniMapBoxScale; - this.svgBoxLeft = miniMapBoxLeft; - this.svgBoxTop = miniMapBoxTop; + this.$refs.svgBox.innerHTML = svgHTML + this.viewBoxStyle = viewBoxStyle + this.svgBoxScale = miniMapBoxScale + this.svgBoxLeft = miniMapBoxLeft + this.svgBoxTop = miniMapBoxTop }, onMousedown(e) { - this.mindMap.miniMap.onMousedown(e); + this.mindMap.miniMap.onMousedown(e) }, onMousemove(e) { - this.mindMap.miniMap.onMousemove(e); + this.mindMap.miniMap.onMousemove(e) }, onMouseup(e) { - this.mindMap.miniMap.onMouseup(e); - }, - }, -}; + this.mindMap.miniMap.onMouseup(e) + } + } +} \ No newline at end of file + diff --git a/web/src/pages/Edit/components/NodeIcon.vue b/web/src/pages/Edit/components/NodeIcon.vue index 8488bd0a..89eed139 100644 --- a/web/src/pages/Edit/components/NodeIcon.vue +++ b/web/src/pages/Edit/components/NodeIcon.vue @@ -24,7 +24,7 @@ \ No newline at end of file + diff --git a/web/src/pages/Edit/components/NodeImage.vue b/web/src/pages/Edit/components/NodeImage.vue index 133329ba..938ddc3b 100644 --- a/web/src/pages/Edit/components/NodeImage.vue +++ b/web/src/pages/Edit/components/NodeImage.vue @@ -18,7 +18,7 @@ \ No newline at end of file + diff --git a/web/src/pages/Edit/components/NodeImgPreview.vue b/web/src/pages/Edit/components/NodeImgPreview.vue index 9ee92d32..041a5444 100644 --- a/web/src/pages/Edit/components/NodeImgPreview.vue +++ b/web/src/pages/Edit/components/NodeImgPreview.vue @@ -10,32 +10,32 @@ export default { mindMap: { type: Object, default() { - return null; - }, - }, + return null + } + } }, data() { return { - images: [], - }; + images: [] + } }, mounted() { - this.mindMap.on("node_img_dblclick", this.onNodeTmgDblclick); + this.mindMap.on('node_img_dblclick', this.onNodeTmgDblclick) }, - beforeDestroy () { - this.mindMap.off("node_img_dblclick", this.onNodeTmgDblclick); + beforeDestroy() { + this.mindMap.off('node_img_dblclick', this.onNodeTmgDblclick) }, methods: { onNodeTmgDblclick(node, e) { - e.stopPropagation(); - e.preventDefault(); - this.images = [node.nodeData.data.image]; + e.stopPropagation() + e.preventDefault() + this.images = [node.nodeData.data.image] this.$viewerApi({ - images: this.images, - }); - }, - }, -}; + images: this.images + }) + } + } +} diff --git a/web/src/pages/Edit/components/NodeNote.vue b/web/src/pages/Edit/components/NodeNote.vue index 14372bf8..725a25dc 100644 --- a/web/src/pages/Edit/components/NodeNote.vue +++ b/web/src/pages/Edit/components/NodeNote.vue @@ -22,8 +22,8 @@ \ No newline at end of file + diff --git a/web/src/pages/Edit/components/NodeNoteContentShow.vue b/web/src/pages/Edit/components/NodeNoteContentShow.vue index 0b5cdaa8..c8528e34 100644 --- a/web/src/pages/Edit/components/NodeNoteContentShow.vue +++ b/web/src/pages/Edit/components/NodeNoteContentShow.vue @@ -2,13 +2,17 @@
\ No newline at end of file + diff --git a/web/src/pages/Edit/components/Outline.vue b/web/src/pages/Edit/components/Outline.vue index 28b8609d..031b72ba 100644 --- a/web/src/pages/Edit/components/Outline.vue +++ b/web/src/pages/Edit/components/Outline.vue @@ -5,7 +5,7 @@ - + diff --git a/web/src/pages/Edit/components/Scale.vue b/web/src/pages/Edit/components/Scale.vue index 6c0edc64..e9c9b1d3 100644 --- a/web/src/pages/Edit/components/Scale.vue +++ b/web/src/pages/Edit/components/Scale.vue @@ -17,32 +17,32 @@ * @Desc: 放大缩小 */ export default { - name: "Scale", + name: 'Scale', props: { mindMap: { - type: Object, - }, + type: Object + } }, data() { return { - scaleNum: 100, - }; + scaleNum: 100 + } }, watch: { mindMap(val, oldVal) { if (val && !oldVal) { - this.mindMap.on("scale", (scale) => { - this.scaleNum = this.toPer(scale); - }); + this.mindMap.on('scale', scale => { + this.scaleNum = this.toPer(scale) + }) this.scaleNum = this.toPer(this.mindMap.view.scale) } - }, + } }, methods: { - /** - * @Author: 王林25 - * @Date: 2021-11-25 14:20:16 - * @Desc: 转换成百分数 + /** + * @Author: 王林25 + * @Date: 2021-11-25 14:20:16 + * @Desc: 转换成百分数 */ toPer(scale) { return (scale * 100).toFixed(0) @@ -54,7 +54,7 @@ export default { * @Desc: 缩小 */ narrow() { - this.mindMap.view.narrow(); + this.mindMap.view.narrow() }, /** @@ -63,10 +63,10 @@ export default { * @Desc: 放大 */ enlarge() { - this.mindMap.view.enlarge(); - }, - }, -}; + this.mindMap.view.enlarge() + } + } +}