diff --git a/simple-mind-map/index.js b/simple-mind-map/index.js index 9f57350a..e0257fcc 100644 --- a/simple-mind-map/index.js +++ b/simple-mind-map/index.js @@ -7,7 +7,7 @@ import Style from './src/Style' import KeyCommand from './src/KeyCommand' import Command from './src/Command' import BatchExecution from './src/BatchExecution' -import { layoutValueList } from './src/utils/constant' +import { layoutValueList, CONSTANTS } from './src/utils/constant' import { SVG } from '@svgdotjs/svg.js' import { simpleDeepClone } from './src/utils' import defaultTheme from './src/themes/default' @@ -17,7 +17,7 @@ const defaultOpt = { // 是否只读 readonly: false, // 布局 - layout: 'logicalStructure', + layout: CONSTANTS.LAYOUT.LOGICAL_STRUCTURE, // 主题 theme: 'default', // 内置主题:default(默认主题) // 主题配置,会和所选择的主题进行合并 @@ -66,7 +66,7 @@ const defaultOpt = { // 可以传一个函数,回调参数为事件对象 customHandleMousewheel: null, // 鼠标滚动的行为,如果customHandleMousewheel传了自定义函数,这个属性不生效 - mousewheelAction: 'zoom',// zoom(放大缩小)、move(上下移动) + mousewheelAction: CONSTANTS.MOUSE_WHEEL_ACTION.ZOOM,// zoom(放大缩小)、move(上下移动) // 当mousewheelAction设为move时,可以通过该属性控制鼠标滚动一下视图移动的步长,单位px mousewheelMoveStep: 100, // 默认插入的二级节点的文字 @@ -145,7 +145,7 @@ class MindMap { handleOpt(opt) { // 检查布局配置 if (!layoutValueList.includes(opt.layout)) { - opt.layout = 'logicalStructure' + opt.layout = CONSTANTS.LAYOUT.LOGICAL_STRUCTURE } // 检查主题配置 opt.theme = opt.theme && theme[opt.theme] ? opt.theme : 'default' @@ -206,7 +206,7 @@ class MindMap { setTheme(theme) { this.renderer.clearAllActive() this.opt.theme = theme - this.render(null, 'changeTheme') + this.render(null, CONSTANTS.CHANGE_THEME) } // 获取当前主题 @@ -217,7 +217,7 @@ class MindMap { // 设置主题配置 setThemeConfig(config) { this.opt.themeConfig = config - this.render(null, 'changeTheme') + this.render(null, CONSTANTS.CHANGE_THEME) } // 获取自定义主题配置 @@ -249,7 +249,7 @@ class MindMap { setLayout(layout) { // 检查布局配置 if (!layoutValueList.includes(layout)) { - layout = 'logicalStructure' + layout = CONSTANTS.LAYOUT.LOGICAL_STRUCTURE } this.opt.layout = layout this.renderer.setLayout() @@ -326,10 +326,10 @@ class MindMap { // 设置只读模式、编辑模式 setMode(mode) { - if (!['readonly', 'edit'].includes(mode)) { + if (![CONSTANTS.MODE.READONLY, CONSTANTS.MODE.EDIT].includes(mode)) { return } - this.opt.readonly = mode === 'readonly' + this.opt.readonly = mode === CONSTANTS.MODE.READONLY if (this.opt.readonly) { // 取消当前激活的元素 this.renderer.clearAllActive() diff --git a/simple-mind-map/src/Event.js b/simple-mind-map/src/Event.js index cccc79d7..bc3f8ee3 100644 --- a/simple-mind-map/src/Event.js +++ b/simple-mind-map/src/Event.js @@ -1,4 +1,5 @@ import EventEmitter from 'eventemitter3' +import { CONSTANTS } from './utils/constant' // 事件类 class Event extends EventEmitter { @@ -107,15 +108,15 @@ class Event extends EventEmitter { let dir // 解决mac触控板双指缩放方向相反的问题 if (e.ctrlKey) { - if (e.deltaY > 0) dir = 'up' - if (e.deltaY < 0) dir = 'down' - if (e.deltaX > 0) dir = 'left' - if (e.deltaX < 0) dir = 'right' + if (e.deltaY > 0) dir = CONSTANTS.DIR.UP + if (e.deltaY < 0) dir = CONSTANTS.DIR.DOWN + if (e.deltaX > 0) dir = CONSTANTS.DIR.LEFT + if (e.deltaX < 0) dir = CONSTANTS.DIR.RIGHT } else { - if ((e.wheelDeltaY || e.detail) > 0) dir = 'up' - if ((e.wheelDeltaY || e.detail) < 0) dir = 'down' - if ((e.wheelDeltaX || e.detail) > 0) dir = 'left' - if ((e.wheelDeltaX || e.detail) < 0) dir = 'right' + if ((e.wheelDeltaY || e.detail) > 0) dir = CONSTANTS.DIR.UP + if ((e.wheelDeltaY || e.detail) < 0) dir = CONSTANTS.DIR.DOWN + if ((e.wheelDeltaX || e.detail) > 0) dir = CONSTANTS.DIR.LEFT + if ((e.wheelDeltaX || e.detail) < 0) dir = CONSTANTS.DIR.RIGHT } this.emit('mousewheel', e, dir, this) } diff --git a/simple-mind-map/src/KeyboardNavigation.js b/simple-mind-map/src/KeyboardNavigation.js index 0408dfae..c5adf041 100644 --- a/simple-mind-map/src/KeyboardNavigation.js +++ b/simple-mind-map/src/KeyboardNavigation.js @@ -1,4 +1,5 @@ import { bfsWalk } from './utils' +import { CONSTANTS } from './utils/constant' // 键盘导航类 class KeyboardNavigation { @@ -7,17 +8,17 @@ class KeyboardNavigation { this.opt = opt this.mindMap = opt.mindMap this.onKeyup = this.onKeyup.bind(this) - this.mindMap.keyCommand.addShortcut('Left', () => { - this.onKeyup('Left') + this.mindMap.keyCommand.addShortcut(CONSTANTS.KEY_DIR.LEFT, () => { + this.onKeyup(CONSTANTS.KEY_DIR.LEFT) }) - this.mindMap.keyCommand.addShortcut('Up', () => { - this.onKeyup('Up') + this.mindMap.keyCommand.addShortcut(CONSTANTS.KEY_DIR.UP, () => { + this.onKeyup(CONSTANTS.KEY_DIR.UP) }) - this.mindMap.keyCommand.addShortcut('Right', () => { - this.onKeyup('Right') + this.mindMap.keyCommand.addShortcut(CONSTANTS.KEY_DIR.RIGHT, () => { + this.onKeyup(CONSTANTS.KEY_DIR.RIGHT) }) - this.mindMap.keyCommand.addShortcut('Down', () => { - this.onKeyup('Down') + this.mindMap.keyCommand.addShortcut(CONSTANTS.KEY_DIR.DOWN, () => { + this.onKeyup(CONSTANTS.KEY_DIR.DOWN) }) } @@ -101,19 +102,19 @@ class KeyboardNavigation { let { left, top, right, bottom } = rect let match = false // 按下了左方向键 - if (dir === 'Left') { + if (dir === CONSTANTS.KEY_DIR.LEFT) { // 判断节点是否在当前节点的左侧 match = right <= currentActiveNodeRect.left // 按下了右方向键 - } else if (dir === 'Right') { + } else if (dir === CONSTANTS.KEY_DIR.RIGHT) { // 判断节点是否在当前节点的右侧 match = left >= currentActiveNodeRect.right // 按下了上方向键 - } else if (dir === 'Up') { + } else if (dir === CONSTANTS.KEY_DIR.UP) { // 判断节点是否在当前节点的上面 match = bottom <= currentActiveNodeRect.top // 按下了下方向键 - } else if (dir === 'Down') { + } else if (dir === CONSTANTS.KEY_DIR.DOWN) { // 判断节点是否在当前节点的下面 match = top >= currentActiveNodeRect.bottom } @@ -136,22 +137,22 @@ class KeyboardNavigation { let rect = this.getNodeRect(node) let { left, top, right, bottom } = rect let match = false - if (dir === 'Left') { + if (dir === CONSTANTS.KEY_DIR.LEFT) { match = left < currentActiveNodeRect.left && top < currentActiveNodeRect.bottom && bottom > currentActiveNodeRect.top - } else if (dir === 'Right') { + } else if (dir === CONSTANTS.KEY_DIR.RIGHT) { match = right > currentActiveNodeRect.right && top < currentActiveNodeRect.bottom && bottom > currentActiveNodeRect.top - } else if (dir === 'Up') { + } else if (dir === CONSTANTS.KEY_DIR.UP) { match = top < currentActiveNodeRect.top && left < currentActiveNodeRect.right && right > currentActiveNodeRect.left - } else if (dir === 'Down') { + } else if (dir === CONSTANTS.KEY_DIR.DOWN) { match = bottom > currentActiveNodeRect.bottom && left < currentActiveNodeRect.right && @@ -185,13 +186,13 @@ class KeyboardNavigation { let offsetY = ccY - cY if (offsetX === 0 && offsetY === 0) return let match = false - if (dir === 'Left') { + if (dir === CONSTANTS.KEY_DIR.LEFT) { match = offsetX <= 0 && offsetX <= offsetY && offsetX <= -offsetY - } else if (dir === 'Right') { + } else if (dir === CONSTANTS.KEY_DIR.RIGHT) { match = offsetX > 0 && offsetX >= -offsetY && offsetX >= offsetY - } else if (dir === 'Up') { + } else if (dir === CONSTANTS.KEY_DIR.UP) { match = offsetY <= 0 && offsetY < offsetX && offsetY < -offsetX - } else if (dir === 'Down') { + } else if (dir === CONSTANTS.KEY_DIR.DOWN) { match = offsetY > 0 && -offsetY < offsetX && offsetY > offsetX } if (match) { diff --git a/simple-mind-map/src/Node.js b/simple-mind-map/src/Node.js index 07402290..b1e4aecc 100644 --- a/simple-mind-map/src/Node.js +++ b/simple-mind-map/src/Node.js @@ -6,6 +6,7 @@ import nodeGeneralizationMethods from './utils/nodeGeneralization' import nodeExpandBtnMethods from './utils/nodeExpandBtn' import nodeCommandWrapsMethods from './utils/nodeCommandWraps' import nodeCreateContentsMethods from './utils/nodeCreateContents' +import { CONSTANTS } from './utils/constant' // 节点类 @@ -452,7 +453,7 @@ class Node { // 更新节点形状样式 updateNodeShape() { const shape = this.getShape() - this.style[shape === 'rectangle' ? 'rect' : 'shape'](this.shapeNode) + this.style[shape === CONSTANTS.SHAPE.RECTANGLE ? 'rect' : 'shape'](this.shapeNode) } // 递归渲染 @@ -615,7 +616,7 @@ class Node { getShape() { // 节点使用功能横线风格的话不支持设置形状,直接使用默认的矩形 return this.mindMap.themeConfig.nodeUseLineStyle - ? 'rectangle' + ? CONSTANTS.SHAPE.RECTANGLE : this.style.getStyle('shape', false, false) } diff --git a/simple-mind-map/src/Render.js b/simple-mind-map/src/Render.js index 72f8076b..633a1b49 100644 --- a/simple-mind-map/src/Render.js +++ b/simple-mind-map/src/Render.js @@ -7,17 +7,18 @@ import TextEdit from './TextEdit' import { copyNodeTree, simpleDeepClone, walk } from './utils' import { shapeList } from './Shape' import { lineStyleProps } from './themes/default' +import { CONSTANTS } from './utils/constant' // 布局列表 const layouts = { // 逻辑结构图 - logicalStructure: LogicalStructure, + [CONSTANTS.LAYOUT.LOGICAL_STRUCTURE]: LogicalStructure, // 思维导图 - mindMap: MindMap, + [CONSTANTS.LAYOUT.MIND_MAP]: MindMap, // 目录组织图 - catalogOrganization: CatalogOrganization, + [CONSTANTS.LAYOUT.CATALOG_ORGANIZATION]: CatalogOrganization, // 组织结构图 - organizationStructure: OrganizationStructure + [CONSTANTS.LAYOUT.ORGANIZATION_STRUCTURE]: OrganizationStructure } // 渲染 @@ -56,7 +57,7 @@ class Render { this.layout = new ( layouts[this.mindMap.opt.layout] ? layouts[this.mindMap.opt.layout] - : layouts.logicalStructure + : layouts[CONSTANTS.LAYOUT.LOGICAL_STRUCTURE] )(this) } diff --git a/simple-mind-map/src/Shape.js b/simple-mind-map/src/Shape.js index b2b8a724..b0df207b 100644 --- a/simple-mind-map/src/Shape.js +++ b/simple-mind-map/src/Shape.js @@ -1,4 +1,5 @@ import { Rect, Polygon, Path } from '@svgdotjs/svg.js' +import { CONSTANTS } from './utils/constant' // 节点形状类 export default class Shape { @@ -15,37 +16,37 @@ export default class Shape { const actHeight = height + paddingY * 2 const actOffset = Math.abs(actWidth - actHeight) switch (shape) { - case 'roundedRectangle': + case CONSTANTS.SHAPE.ROUNDED_RECTANGLE: return { paddingX: height > width ? (height - width) / 2 : 0, paddingY: 0 } - case 'diamond': + case CONSTANTS.SHAPE.DIAMOND: return { paddingX: width / 2, paddingY: height / 2 } - case 'parallelogram': + case CONSTANTS.SHAPE.PARALLELOGRAM: return { paddingX: paddingX <= 0 ? defaultPaddingX : 0, paddingY: 0 } - case 'outerTriangularRectangle': + case CONSTANTS.SHAPE.OUTER_TRIANGULAR_RECTANGLE: return { paddingX: paddingX <= 0 ? defaultPaddingX : 0, paddingY: 0 } - case 'innerTriangularRectangle': + case CONSTANTS.SHAPE.INNER_TRIANGULAR_RECTANGLE: return { paddingX: paddingX <= 0 ? defaultPaddingX : 0, paddingY: 0 } - case 'ellipse': + case CONSTANTS.SHAPE.ELLIPSE: return { paddingX: paddingX <= 0 ? defaultPaddingX : 0, paddingY: paddingY <= 0 ? defaultPaddingY : 0 } - case 'circle': + case CONSTANTS.SHAPE.CIRCLE: return { paddingX: actHeight > actWidth ? actOffset / 2 : 0, paddingY: actHeight < actWidth ? actOffset / 2 : 0 @@ -64,30 +65,30 @@ export default class Shape { let { width, height } = this.node let node = null // 矩形 - if (shape === 'rectangle') { + if (shape === CONSTANTS.SHAPE.RECTANGLE) { node = new Rect().size(width, height) - } else if (shape === 'diamond') { + } else if (shape === CONSTANTS.SHAPE.DIAMOND) { // 菱形 node = this.createDiamond() - } else if (shape === 'parallelogram') { + } else if (shape === CONSTANTS.SHAPE.PARALLELOGRAM) { // 平行四边形 node = this.createParallelogram() - } else if (shape === 'roundedRectangle') { + } else if (shape === CONSTANTS.SHAPE.ROUNDED_RECTANGLE) { // 圆角矩形 node = this.createRoundedRectangle() - } else if (shape === 'octagonalRectangle') { + } else if (shape === CONSTANTS.SHAPE.OCTAGONAL_RECTANGLE) { // 八角矩形 node = this.createOctagonalRectangle() - } else if (shape === 'outerTriangularRectangle') { + } else if (shape === CONSTANTS.SHAPE.OUTER_TRIANGULAR_RECTANGLE) { // 外三角矩形 node = this.createOuterTriangularRectangle() - } else if (shape === 'innerTriangularRectangle') { + } else if (shape === CONSTANTS.SHAPE.INNER_TRIANGULAR_RECTANGLE) { // 内三角矩形 node = this.createInnerTriangularRectangle() - } else if (shape === 'ellipse') { + } else if (shape === CONSTANTS.SHAPE.ELLIPSE) { // 椭圆 node = this.createEllipse() - } else if (shape === 'circle') { + } else if (shape === CONSTANTS.SHAPE.CIRCLE) { // 圆 node = this.createCircle() } @@ -216,13 +217,13 @@ export default class Shape { // 形状列表 export const shapeList = [ - 'rectangle', - 'diamond', - 'parallelogram', - 'roundedRectangle', - 'octagonalRectangle', - 'outerTriangularRectangle', - 'innerTriangularRectangle', - 'ellipse', - 'circle' + CONSTANTS.SHAPE.RECTANGLE, + CONSTANTS.SHAPE.DIAMOND, + CONSTANTS.SHAPE.PARALLELOGRAM, + CONSTANTS.SHAPE.ROUNDED_RECTANGLE, + CONSTANTS.SHAPE.OCTAGONAL_RECTANGLE, + CONSTANTS.SHAPE.OUTER_TRIANGULAR_RECTANGLE, + CONSTANTS.SHAPE.INNER_TRIANGULAR_RECTANGLE, + CONSTANTS.SHAPE.ELLIPSE, + CONSTANTS.SHAPE.CIRCLE ] diff --git a/simple-mind-map/src/View.js b/simple-mind-map/src/View.js index 3aa10747..16f160bc 100644 --- a/simple-mind-map/src/View.js +++ b/simple-mind-map/src/View.js @@ -1,3 +1,5 @@ +import { CONSTANTS } from './utils/constant' + // 视图操作类 class View { // 构造函数 @@ -58,35 +60,35 @@ class View { if (this.mindMap.opt.customHandleMousewheel && typeof this.mindMap.opt.customHandleMousewheel === 'function') { return this.mindMap.opt.customHandleMousewheel(e) } - if (this.mindMap.opt.mousewheelAction === 'zoom') { + if (this.mindMap.opt.mousewheelAction === CONSTANTS.MOUSE_WHEEL_ACTION.ZOOM) { switch (dir) { // 鼠标滚轮,向上和向左,都是缩小 - case 'up': - case 'left': + case CONSTANTS.DIR.UP: + case CONSTANTS.DIR.LEFT: this.narrow() break // 鼠标滚轮,向下和向右,都是放大 - case 'down': - case 'right': + case CONSTANTS.DIR.DOWN: + case CONSTANTS.DIR.RIGHT: this.enlarge() break } } else { switch (dir){ // 上移 - case 'down': + case CONSTANTS.DIR.DOWN: this.translateY(-this.mindMap.opt.mousewheelMoveStep) break // 下移 - case 'up': + case CONSTANTS.DIR.UP: this.translateY(this.mindMap.opt.mousewheelMoveStep) break // 右移 - case 'left': + case CONSTANTS.DIR.LEFT: this.translateX(-this.mindMap.opt.mousewheelMoveStep) break // 左移 - case 'right': + case CONSTANTS.DIR.RIGHT: this.translateX(this.mindMap.opt.mousewheelMoveStep) break } diff --git a/simple-mind-map/src/layouts/Base.js b/simple-mind-map/src/layouts/Base.js index 436c41e4..517f7582 100644 --- a/simple-mind-map/src/layouts/Base.js +++ b/simple-mind-map/src/layouts/Base.js @@ -1,4 +1,5 @@ import Node from '../Node' +import { CONSTANTS } from '../utils/constant' // 布局基类 class Base { @@ -42,7 +43,7 @@ class Base { newNode.reset() newNode.layerIndex = layerIndex // 主题或主题配置改变了需要重新计算节点大小和布局 - if (this.renderer.renderSource === 'changeTheme') { + if (this.renderer.renderSource === CONSTANTS.CHANGE_THEME) { newNode.getSize() newNode.needLayout = true } diff --git a/simple-mind-map/src/utils/constant.js b/simple-mind-map/src/utils/constant.js index d13d4231..689a450a 100644 --- a/simple-mind-map/src/utils/constant.js +++ b/simple-mind-map/src/utils/constant.js @@ -22,32 +22,6 @@ export const tagColorList = [ } ] -// 布局结构列表 -export const layoutList = [ - { - name: '逻辑结构图', - value: 'logicalStructure', - }, - { - name: '思维导图', - value: 'mindMap', - }, - { - name: '组织结构图', - value: 'organizationStructure', - }, - { - name: '目录组织图', - value: 'catalogOrganization', - } -] -export const layoutValueList = [ - 'logicalStructure', - 'mindMap', - 'catalogOrganization', - 'organizationStructure' -] - // 主题列表 export const themeList = [ { @@ -139,3 +113,71 @@ export const themeList = [ value: 'romanticPurple', } ] + +// 常量 +export const CONSTANTS = { + CHANGE_THEME: 'changeTheme', + MODE: { + READONLY: 'readonly', + EDIT: 'edit' + }, + LAYOUT: { + LOGICAL_STRUCTURE: 'logicalStructure', + MIND_MAP: 'mindMap', + ORGANIZATION_STRUCTURE: 'organizationStructure', + CATALOG_ORGANIZATION: 'catalogOrganization' + }, + DIR: { + UP: 'up', + LEFT: 'left', + DOWN: 'down', + RIGHT: 'right' + }, + KEY_DIR: { + LEFT: 'Left', + UP: 'Up', + RIGHT: 'Right', + DOWN: 'Down' + }, + SHAPE: { + RECTANGLE: 'rectangle', + DIAMOND: 'diamond', + PARALLELOGRAM: 'parallelogram', + ROUNDED_RECTANGLE: 'roundedRectangle', + OCTAGONAL_RECTANGLE: 'octagonalRectangle', + OUTER_TRIANGULAR_RECTANGLE: 'outerTriangularRectangle', + INNER_TRIANGULAR_RECTANGLE: 'innerTriangularRectangle', + ELLIPSE: 'ellipse', + CIRCLE: 'circle' + }, + MOUSE_WHEEL_ACTION: { + ZOOM: 'zoom', + MOVE: 'move' + } +} + +// 布局结构列表 +export const layoutList = [ + { + name: '逻辑结构图', + value: CONSTANTS.LAYOUT.LOGICAL_STRUCTURE, + }, + { + name: '思维导图', + value: CONSTANTS.LAYOUT.MIND_MAP, + }, + { + name: '组织结构图', + value: CONSTANTS.LAYOUT.ORGANIZATION_STRUCTURE, + }, + { + name: '目录组织图', + value: CONSTANTS.LAYOUT.CATALOG_ORGANIZATION, + } +] +export const layoutValueList = [ + CONSTANTS.LAYOUT.LOGICAL_STRUCTURE, + CONSTANTS.LAYOUT.MIND_MAP, + CONSTANTS.LAYOUT.CATALOG_ORGANIZATION, + CONSTANTS.LAYOUT.ORGANIZATION_STRUCTURE +] \ No newline at end of file