节点支持多种形状开发完成
This commit is contained in:
parent
13a4b12ad4
commit
5b5aab1c9e
@ -18,6 +18,8 @@
|
|||||||
|
|
||||||
- [x] 支持节点自由拖拽、拖拽调整
|
- [x] 支持节点自由拖拽、拖拽调整
|
||||||
|
|
||||||
|
- [x] 支持多种节点形状
|
||||||
|
|
||||||
## 目录介绍
|
## 目录介绍
|
||||||
|
|
||||||
1.`simple-mind-map`
|
1.`simple-mind-map`
|
||||||
@ -86,7 +88,7 @@ npm run build
|
|||||||
|
|
||||||
# 安装
|
# 安装
|
||||||
|
|
||||||
> 当然仓库版本:0.2.3,当前npm版本:0.2.3
|
> 当然仓库版本:0.2.4,当前npm版本:0.2.3
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm i simple-mind-map
|
npm i simple-mind-map
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "simple-mind-map",
|
"name": "simple-mind-map",
|
||||||
"version": "0.2.3",
|
"version": "0.2.4",
|
||||||
"description": "一个简单的web在线思维导图",
|
"description": "一个简单的web在线思维导图",
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import Style from './Style'
|
import Style from './Style'
|
||||||
|
import Shape from './Shape'
|
||||||
import {
|
import {
|
||||||
resizeImgSize,
|
resizeImgSize,
|
||||||
asyncRun
|
asyncRun
|
||||||
@ -43,6 +44,12 @@ class Node {
|
|||||||
this.themeConfig = this.mindMap.themeConfig
|
this.themeConfig = this.mindMap.themeConfig
|
||||||
// 样式实例
|
// 样式实例
|
||||||
this.style = new Style(this, this.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.isRoot = opt.isRoot === undefined ? false : opt.isRoot
|
||||||
// 是否是概要节点
|
// 是否是概要节点
|
||||||
@ -331,9 +338,16 @@ class Node {
|
|||||||
// 间距
|
// 间距
|
||||||
let margin = imgContentHeight > 0 && textContentHeight > 0 ? this.blockContentMargin : 0
|
let margin = imgContentHeight > 0 && textContentHeight > 0 ? this.blockContentMargin : 0
|
||||||
let { paddingX, paddingY } = this.getPaddingVale()
|
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 {
|
return {
|
||||||
width: Math.max(imgContentWidth, textContentWidth) + paddingX * 2,
|
width: _width + paddingX * 2 + shapePaddingX * 2,
|
||||||
height: imgContentHeight + textContentHeight + paddingY * 2 + margin
|
height: _height + paddingY * 2 + margin + shapePaddingY * 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -542,6 +556,16 @@ class Node {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* javascript comment
|
||||||
|
* @Author: 王林
|
||||||
|
* @Date: 2022-09-12 22:02:07
|
||||||
|
* @Desc: 获取节点形状
|
||||||
|
*/
|
||||||
|
getShape() {
|
||||||
|
return this.style.getStyle('shape', false, false)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* javascript comment
|
* javascript comment
|
||||||
* @Author: 王林25
|
* @Author: 王林25
|
||||||
@ -555,6 +579,7 @@ class Node {
|
|||||||
textContentItemMargin
|
textContentItemMargin
|
||||||
} = this
|
} = this
|
||||||
let { paddingY } = this.getPaddingVale()
|
let { paddingY } = this.getPaddingVale()
|
||||||
|
paddingY += this.shapePadding.paddingY
|
||||||
// 创建组
|
// 创建组
|
||||||
this.group = new G()
|
this.group = new G()
|
||||||
// 概要节点添加一个带所属节点id的类名
|
// 概要节点添加一个带所属节点id的类名
|
||||||
@ -563,8 +588,9 @@ class Node {
|
|||||||
}
|
}
|
||||||
this.draw.add(this.group)
|
this.draw.add(this.group)
|
||||||
this.update(true)
|
this.update(true)
|
||||||
// 节点矩形
|
// 节点形状
|
||||||
this.style.rect(this.group.rect(width, height))
|
const shape = this.getShape()
|
||||||
|
this.style[shape === 'rectangle' ? 'rect' : 'shape'](this.shapeInstance.createShape())
|
||||||
// 图片节点
|
// 图片节点
|
||||||
let imgHeight = 0
|
let imgHeight = 0
|
||||||
if (this._imgData) {
|
if (this._imgData) {
|
||||||
@ -1206,6 +1232,16 @@ class Node {
|
|||||||
setTag(tag) {
|
setTag(tag) {
|
||||||
this.mindMap.execCommand('SET_NODE_TAG', this, 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
|
export default Node
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import CatalogOrganization from './layouts/CatalogOrganization'
|
|||||||
import OrganizationStructure from './layouts/OrganizationStructure'
|
import OrganizationStructure from './layouts/OrganizationStructure'
|
||||||
import TextEdit from './TextEdit'
|
import TextEdit from './TextEdit'
|
||||||
import { copyNodeTree, simpleDeepClone, walk } from './utils'
|
import { copyNodeTree, simpleDeepClone, walk } from './utils'
|
||||||
|
import { shapeList } from './Shape';
|
||||||
|
|
||||||
// 布局列表
|
// 布局列表
|
||||||
const layouts = {
|
const layouts = {
|
||||||
@ -175,6 +176,9 @@ class Render {
|
|||||||
// 一键整理布局
|
// 一键整理布局
|
||||||
this.resetLayout = this.resetLayout.bind(this)
|
this.resetLayout = this.resetLayout.bind(this)
|
||||||
this.mindMap.command.add('RESET_LAYOUT', this.resetLayout)
|
this.mindMap.command.add('RESET_LAYOUT', this.resetLayout)
|
||||||
|
// 设置节点形状
|
||||||
|
this.setNodeShape = this.setNodeShape.bind(this)
|
||||||
|
this.mindMap.command.add('SET_NODE_SHAPE', this.setNodeShape)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -977,6 +981,22 @@ class Render {
|
|||||||
}, null, true, 0, 0)
|
}, 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: 王林
|
* @Author: 王林
|
||||||
* @Date: 2021-05-04 14:19:48
|
* @Date: 2021-05-04 14:19:48
|
||||||
|
|||||||
265
simple-mind-map/src/Shape.js
Normal file
265
simple-mind-map/src/Shape.js
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
/**
|
||||||
|
* @Author: 王林
|
||||||
|
* @Date: 2022-08-22 21:32:50
|
||||||
|
* @Desc: 节点形状类
|
||||||
|
*/
|
||||||
|
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: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(`
|
||||||
|
${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(`
|
||||||
|
${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(`
|
||||||
|
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(`
|
||||||
|
${0}, ${w}
|
||||||
|
${w}, ${0}
|
||||||
|
${width - w}, ${0}
|
||||||
|
${width}, ${w}
|
||||||
|
${width}, ${height - w}
|
||||||
|
${width - w}, ${height}
|
||||||
|
${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(`
|
||||||
|
${paddingX}, ${0}
|
||||||
|
${width - paddingX}, ${0}
|
||||||
|
${width}, ${height / 2}
|
||||||
|
${width - paddingX}, ${height}
|
||||||
|
${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(`
|
||||||
|
${0}, ${0}
|
||||||
|
${width}, ${0}
|
||||||
|
${width - paddingX / 2}, ${height / 2}
|
||||||
|
${width}, ${height}
|
||||||
|
${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(`
|
||||||
|
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(`
|
||||||
|
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']
|
||||||
@ -69,19 +69,40 @@ class Style {
|
|||||||
return this.ctx.nodeData.data[prop] !== undefined ? this.ctx.nodeData.data[prop] : defaultConfig[prop]
|
return this.ctx.nodeData.data[prop] !== undefined ? this.ctx.nodeData.data[prop] : defaultConfig[prop]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* javascript comment
|
||||||
|
* @Author: 王林
|
||||||
|
* @Date: 2022-09-12 21:55:57
|
||||||
|
* @Desc: 获取某个样式值
|
||||||
|
*/
|
||||||
|
getStyle(prop, root, isActive) {
|
||||||
|
return this.merge(prop, root, isActive)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Author: 王林
|
* @Author: 王林
|
||||||
* @Date: 2021-04-11 10:12:56
|
* @Date: 2021-04-11 10:12:56
|
||||||
* @Desc: 矩形
|
* @Desc: 矩形
|
||||||
*/
|
*/
|
||||||
rect(node) {
|
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({
|
node.fill({
|
||||||
color: this.merge('fillColor')
|
color: this.merge('fillColor')
|
||||||
}).stroke({
|
}).stroke({
|
||||||
color: this.merge('borderColor'),
|
color: this.merge('borderColor'),
|
||||||
width: this.merge('borderWidth'),
|
width: this.merge('borderWidth'),
|
||||||
dasharray: this.merge('borderDasharray')
|
dasharray: this.merge('borderDasharray')
|
||||||
}).radius(this.merge('borderRadius'))
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -33,6 +33,7 @@ export default {
|
|||||||
backgroundRepeat: 'no-repeat',
|
backgroundRepeat: 'no-repeat',
|
||||||
// 根节点样式
|
// 根节点样式
|
||||||
root: {
|
root: {
|
||||||
|
shape: 'rectangle',
|
||||||
fillColor: '#549688',
|
fillColor: '#549688',
|
||||||
fontFamily: '微软雅黑, Microsoft YaHei',
|
fontFamily: '微软雅黑, Microsoft YaHei',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
@ -53,6 +54,7 @@ export default {
|
|||||||
},
|
},
|
||||||
// 二级节点样式
|
// 二级节点样式
|
||||||
second: {
|
second: {
|
||||||
|
shape: 'rectangle',
|
||||||
marginX: 100,
|
marginX: 100,
|
||||||
marginY: 40,
|
marginY: 40,
|
||||||
fillColor: '#fff',
|
fillColor: '#fff',
|
||||||
@ -75,6 +77,7 @@ export default {
|
|||||||
},
|
},
|
||||||
// 三级及以下节点样式
|
// 三级及以下节点样式
|
||||||
node: {
|
node: {
|
||||||
|
shape: 'rectangle',
|
||||||
marginX: 50,
|
marginX: 50,
|
||||||
marginY: 0,
|
marginY: 0,
|
||||||
fillColor: 'transparent',
|
fillColor: 'transparent',
|
||||||
@ -97,6 +100,7 @@ export default {
|
|||||||
},
|
},
|
||||||
// 概要节点样式
|
// 概要节点样式
|
||||||
generalization: {
|
generalization: {
|
||||||
|
shape: 'rectangle',
|
||||||
marginX: 100,
|
marginX: 100,
|
||||||
marginY: 40,
|
marginY: 40,
|
||||||
fillColor: '#fff',
|
fillColor: '#fff',
|
||||||
@ -117,4 +121,8 @@ export default {
|
|||||||
borderDasharray: 'none',
|
borderDasharray: 'none',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 支持激活样式的属性
|
||||||
|
// 简单来说,会改变节点大小的都不支持在激活时设置,为了性能考虑,节点切换激活态时不会重新计算节点大小
|
||||||
|
export const supportActiveStyle = ['fillColor', 'color', 'fontWeight', 'fontStyle', 'borderColor', 'borderWidth', 'borderDasharray', 'borderRadius', 'textDecoration']
|
||||||
@ -311,4 +311,44 @@ export const shortcutKeyList = [
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
// 形状列表
|
||||||
|
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'
|
||||||
|
}
|
||||||
]
|
]
|
||||||
@ -15,6 +15,7 @@
|
|||||||
size="mini"
|
size="mini"
|
||||||
v-model="style.fontFamily"
|
v-model="style.fontFamily"
|
||||||
placeholder=""
|
placeholder=""
|
||||||
|
:disabled="checkDisabled('fontFamily')"
|
||||||
@change="update('fontFamily')"
|
@change="update('fontFamily')"
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
@ -36,6 +37,7 @@
|
|||||||
style="width: 80px"
|
style="width: 80px"
|
||||||
v-model="style.fontSize"
|
v-model="style.fontSize"
|
||||||
placeholder=""
|
placeholder=""
|
||||||
|
:disabled="checkDisabled('fontSize')"
|
||||||
@change="update('fontSize')"
|
@change="update('fontSize')"
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
@ -54,6 +56,7 @@
|
|||||||
style="width: 80px"
|
style="width: 80px"
|
||||||
v-model="style.lineHeight"
|
v-model="style.lineHeight"
|
||||||
placeholder=""
|
placeholder=""
|
||||||
|
:disabled="checkDisabled('lineHeight')"
|
||||||
@change="update('lineHeight')"
|
@change="update('lineHeight')"
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
@ -69,7 +72,7 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="btnGroup">
|
<div class="btnGroup">
|
||||||
<el-tooltip content="颜色" placement="bottom">
|
<el-tooltip content="颜色" placement="bottom">
|
||||||
<div class="styleBtn" v-popover:popover>
|
<div class="styleBtn" v-popover:popover :class="{ disabled: checkDisabled('color') }">
|
||||||
A
|
A
|
||||||
<span
|
<span
|
||||||
class="colorShow"
|
class="colorShow"
|
||||||
@ -80,7 +83,7 @@
|
|||||||
<el-tooltip content="加粗" placement="bottom">
|
<el-tooltip content="加粗" placement="bottom">
|
||||||
<div
|
<div
|
||||||
class="styleBtn"
|
class="styleBtn"
|
||||||
:class="{ actived: style.fontWeight === 'bold' }"
|
:class="{ actived: style.fontWeight === 'bold', disabled: checkDisabled('fontWeight') }"
|
||||||
@click="toggleFontWeight"
|
@click="toggleFontWeight"
|
||||||
>
|
>
|
||||||
B
|
B
|
||||||
@ -89,7 +92,7 @@
|
|||||||
<el-tooltip content="斜体" placement="bottom">
|
<el-tooltip content="斜体" placement="bottom">
|
||||||
<div
|
<div
|
||||||
class="styleBtn i"
|
class="styleBtn i"
|
||||||
:class="{ actived: style.fontStyle === 'italic' }"
|
:class="{ actived: style.fontStyle === 'italic', disabled: checkDisabled('fontStyle') }"
|
||||||
@click="toggleFontStyle"
|
@click="toggleFontStyle"
|
||||||
>
|
>
|
||||||
I
|
I
|
||||||
@ -99,16 +102,17 @@
|
|||||||
<div
|
<div
|
||||||
class="styleBtn u"
|
class="styleBtn u"
|
||||||
:style="{ textDecoration: style.textDecoration || 'none' }"
|
:style="{ textDecoration: style.textDecoration || 'none' }"
|
||||||
|
:class="{ disabled: checkDisabled('textDecoration') }"
|
||||||
v-popover:popover2
|
v-popover:popover2
|
||||||
>
|
>
|
||||||
U
|
U
|
||||||
</div>
|
</div>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</div>
|
</div>
|
||||||
<el-popover ref="popover" placement="bottom" trigger="click">
|
<el-popover ref="popover" placement="bottom" trigger="click" :disabled="checkDisabled('color')">
|
||||||
<Color :color="style.color" @change="changeFontColor"></Color>
|
<Color :color="style.color" @change="changeFontColor"></Color>
|
||||||
</el-popover>
|
</el-popover>
|
||||||
<el-popover ref="popover2" placement="bottom" trigger="click">
|
<el-popover ref="popover2" placement="bottom" trigger="click" :disabled="checkDisabled('textDecoration')">
|
||||||
<el-radio-group
|
<el-radio-group
|
||||||
size="mini"
|
size="mini"
|
||||||
v-model="style.textDecoration"
|
v-model="style.textDecoration"
|
||||||
@ -129,8 +133,9 @@
|
|||||||
class="block"
|
class="block"
|
||||||
v-popover:popover3
|
v-popover:popover3
|
||||||
:style="{ width: '80px', backgroundColor: style.borderColor }"
|
:style="{ width: '80px', backgroundColor: style.borderColor }"
|
||||||
|
:class="{ disabled: checkDisabled('borderColor') }"
|
||||||
></span>
|
></span>
|
||||||
<el-popover ref="popover3" placement="bottom" trigger="click">
|
<el-popover ref="popover3" placement="bottom" trigger="click" :disabled="checkDisabled('borderColor')">
|
||||||
<Color
|
<Color
|
||||||
:color="style.borderColor"
|
:color="style.borderColor"
|
||||||
@change="changeBorderColor"
|
@change="changeBorderColor"
|
||||||
@ -144,6 +149,7 @@
|
|||||||
style="width: 80px"
|
style="width: 80px"
|
||||||
v-model="style.borderDasharray"
|
v-model="style.borderDasharray"
|
||||||
placeholder=""
|
placeholder=""
|
||||||
|
:disabled="checkDisabled('borderDasharray')"
|
||||||
@change="update('borderDasharray')"
|
@change="update('borderDasharray')"
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
@ -164,6 +170,7 @@
|
|||||||
style="width: 80px"
|
style="width: 80px"
|
||||||
v-model="style.borderWidth"
|
v-model="style.borderWidth"
|
||||||
placeholder=""
|
placeholder=""
|
||||||
|
:disabled="checkDisabled('borderWidth')"
|
||||||
@change="update('borderWidth')"
|
@change="update('borderWidth')"
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
@ -182,6 +189,7 @@
|
|||||||
style="width: 80px"
|
style="width: 80px"
|
||||||
v-model="style.borderRadius"
|
v-model="style.borderRadius"
|
||||||
placeholder=""
|
placeholder=""
|
||||||
|
:disabled="checkDisabled('borderRadius')"
|
||||||
@change="update('borderRadius')"
|
@change="update('borderRadius')"
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
@ -203,12 +211,36 @@
|
|||||||
class="block"
|
class="block"
|
||||||
v-popover:popover4
|
v-popover:popover4
|
||||||
:style="{ backgroundColor: style.fillColor }"
|
:style="{ backgroundColor: style.fillColor }"
|
||||||
|
:class="{ disabled: checkDisabled('fillColor') }"
|
||||||
></span>
|
></span>
|
||||||
<el-popover ref="popover4" placement="bottom" trigger="click">
|
<el-popover ref="popover4" placement="bottom" trigger="click" :disabled="checkDisabled('fillColor')">
|
||||||
<Color :color="style.fillColor" @change="changeFillColor"></Color>
|
<Color :color="style.fillColor" @change="changeFillColor"></Color>
|
||||||
</el-popover>
|
</el-popover>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- 形状 -->
|
||||||
|
<div class="title">形状</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="rowItem">
|
||||||
|
<span class="name">形状</span>
|
||||||
|
<el-select
|
||||||
|
size="mini"
|
||||||
|
style="width: 120px"
|
||||||
|
v-model="style.shape"
|
||||||
|
placeholder=""
|
||||||
|
:disabled="checkDisabled('shape')"
|
||||||
|
@change="update('shape')"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in shapeList"
|
||||||
|
:key="item"
|
||||||
|
:label="item.name"
|
||||||
|
:value="item.value"
|
||||||
|
>
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<!-- 节点内边距 -->
|
<!-- 节点内边距 -->
|
||||||
<div class="title noTop">节点内边距</div>
|
<div class="title noTop">节点内边距</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@ -217,6 +249,7 @@
|
|||||||
<el-slider
|
<el-slider
|
||||||
style="width: 200px"
|
style="width: 200px"
|
||||||
v-model="style.paddingX"
|
v-model="style.paddingX"
|
||||||
|
:disabled="checkDisabled('paddingX')"
|
||||||
@change="update('paddingX')"
|
@change="update('paddingX')"
|
||||||
></el-slider>
|
></el-slider>
|
||||||
</div>
|
</div>
|
||||||
@ -227,6 +260,7 @@
|
|||||||
<el-slider
|
<el-slider
|
||||||
style="width: 200px"
|
style="width: 200px"
|
||||||
v-model="style.paddingY"
|
v-model="style.paddingY"
|
||||||
|
:disabled="checkDisabled('paddingY')"
|
||||||
@change="update('paddingY')"
|
@change="update('paddingY')"
|
||||||
></el-slider>
|
></el-slider>
|
||||||
</div>
|
</div>
|
||||||
@ -246,7 +280,9 @@ import {
|
|||||||
borderDasharrayList,
|
borderDasharrayList,
|
||||||
borderRadiusList,
|
borderRadiusList,
|
||||||
lineHeightList,
|
lineHeightList,
|
||||||
|
shapeList,
|
||||||
} from "@/config";
|
} from "@/config";
|
||||||
|
import { supportActiveStyle } from 'simple-mind-map/src/themes/default';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Author: 王林
|
* @Author: 王林
|
||||||
@ -261,6 +297,8 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
supportActiveStyle,
|
||||||
|
shapeList,
|
||||||
fontFamilyList,
|
fontFamilyList,
|
||||||
fontSizeList,
|
fontSizeList,
|
||||||
borderWidthList,
|
borderWidthList,
|
||||||
@ -270,6 +308,7 @@ export default {
|
|||||||
activeNodes: [],
|
activeNodes: [],
|
||||||
activeTab: "normal",
|
activeTab: "normal",
|
||||||
style: {
|
style: {
|
||||||
|
shape: '',
|
||||||
paddingX: 0,
|
paddingX: 0,
|
||||||
paddingY: 0,
|
paddingY: 0,
|
||||||
color: "",
|
color: "",
|
||||||
@ -289,11 +328,11 @@ export default {
|
|||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.$bus.$on("node_active", (...args) => {
|
this.$bus.$on("node_active", (...args) => {
|
||||||
this.$refs.sidebar.show = false;
|
if (this.$refs.sidebar) this.$refs.sidebar.show = false;
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.activeTab = "normal";
|
this.activeTab = "normal";
|
||||||
this.activeNodes = args[1];
|
this.activeNodes = args[1];
|
||||||
this.$refs.sidebar.show = this.activeNodes.length > 0;
|
if (this.$refs.sidebar) this.$refs.sidebar.show = this.activeNodes.length > 0;
|
||||||
this.initNodeStyle();
|
this.initNodeStyle();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -308,6 +347,15 @@ export default {
|
|||||||
this.initNodeStyle();
|
this.initNodeStyle();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: 王林
|
||||||
|
* @Date: 2022-09-12 22:16:56
|
||||||
|
* @Desc: 检查是否禁用
|
||||||
|
*/
|
||||||
|
checkDisabled(prop) {
|
||||||
|
return this.activeTab === 'active' && !this.supportActiveStyle.includes(prop)
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Author: 王林
|
* @Author: 王林
|
||||||
* @Date: 2021-05-05 09:48:52
|
* @Date: 2021-05-05 09:48:52
|
||||||
@ -319,6 +367,7 @@ export default {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
[
|
[
|
||||||
|
"shape",
|
||||||
"paddingX",
|
"paddingX",
|
||||||
"paddingY",
|
"paddingY",
|
||||||
"color",
|
"color",
|
||||||
@ -472,6 +521,13 @@ export default {
|
|||||||
border: 1px solid #dcdfe6;
|
border: 1px solid #dcdfe6;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
|
&.disabled {
|
||||||
|
background-color: #F5F7FA !important;
|
||||||
|
border-color: #E4E7ED !important;
|
||||||
|
color: #C0C4CC !important;
|
||||||
|
cursor: not-allowed !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -492,6 +548,13 @@ export default {
|
|||||||
background-color: #eee;
|
background-color: #eee;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.disabled {
|
||||||
|
background-color: #F5F7FA !important;
|
||||||
|
border-color: #E4E7ED !important;
|
||||||
|
color: #C0C4CC !important;
|
||||||
|
cursor: not-allowed !important;
|
||||||
|
}
|
||||||
|
|
||||||
&.i {
|
&.i {
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user