@logicflow/extension 2.0.0-beta.1 → 2.0.0-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +361 -6
- package/dist/index.css +63 -0
- package/dist/index.min.js +32 -2
- package/es/NodeResize/control/Control.d.ts +3 -3
- package/es/NodeResize/control/Control.js +13 -3
- package/es/NodeResize/control/Control.js.map +1 -1
- package/es/NodeResize/index.d.ts +4 -0
- package/es/NodeResize/index.js.map +1 -1
- package/es/NodeResize/node/DiamondResize.d.ts +1 -0
- package/es/NodeResize/node/DiamondResize.js +2 -1
- package/es/NodeResize/node/DiamondResize.js.map +1 -1
- package/es/NodeResize/node/EllipseResize.d.ts +1 -0
- package/es/NodeResize/node/EllipseResize.js +2 -1
- package/es/NodeResize/node/EllipseResize.js.map +1 -1
- package/es/NodeResize/node/HtmlResize.js +1 -1
- package/es/NodeResize/node/HtmlResize.js.map +1 -1
- package/es/NodeResize/node/RectResize.js +1 -1
- package/es/NodeResize/node/RectResize.js.map +1 -1
- package/es/bpmn/constant.d.ts +1 -1
- package/es/bpmn/constant.js +3 -0
- package/es/bpmn/constant.js.map +1 -1
- package/es/bpmn/index.d.ts +3 -6
- package/es/bpmn/index.js +5 -7
- package/es/bpmn/index.js.map +1 -1
- package/es/bpmn-elements/presets/Pool/Pool.d.ts +21 -1
- package/es/components/control/index.d.ts +4 -4
- package/es/components/control/index.js.map +1 -1
- package/es/components/highlight/index.d.ts +6 -4
- package/es/components/highlight/index.js +32 -5
- package/es/components/highlight/index.js.map +1 -1
- package/es/components/menu/index.d.ts +1 -1
- package/es/components/menu/index.js +9 -10
- package/es/components/menu/index.js.map +1 -1
- package/es/components/mini-map/index.d.ts +1 -1
- package/es/components/mini-map/index.js +2 -2
- package/es/components/mini-map/index.js.map +1 -1
- package/es/components/selection-select/index.d.ts +1 -1
- package/es/components/selection-select/index.js.map +1 -1
- package/es/dynamic-group/index.d.ts +106 -0
- package/es/dynamic-group/index.js +536 -0
- package/es/dynamic-group/index.js.map +1 -0
- package/es/dynamic-group/model.d.ts +135 -0
- package/es/dynamic-group/model.js +413 -0
- package/es/dynamic-group/model.js.map +1 -0
- package/es/dynamic-group/node.d.ts +16 -0
- package/es/dynamic-group/node.js +143 -0
- package/es/dynamic-group/node.js.map +1 -0
- package/es/dynamic-group/utils.d.ts +17 -0
- package/es/dynamic-group/utils.js +27 -0
- package/es/dynamic-group/utils.js.map +1 -0
- package/es/index.css +63 -0
- package/es/index.d.ts +16 -8
- package/es/index.js +24 -8
- package/es/index.js.map +1 -1
- package/es/insert-node-in-polyline/index.js +3 -3
- package/es/insert-node-in-polyline/index.js.map +1 -1
- package/es/materials/group/GroupNode.d.ts +6 -10
- package/es/materials/group/GroupNode.js +8 -6
- package/es/materials/group/GroupNode.js.map +1 -1
- package/es/materials/group/index.d.ts +5 -5
- package/es/materials/group/index.js +25 -26
- package/es/materials/group/index.js.map +1 -1
- package/es/materials/node-selection/index.d.ts +6 -1
- package/es/materials/node-selection/index.js +64 -56
- package/es/materials/node-selection/index.js.map +1 -1
- package/es/mindmap/index.d.ts +2 -2
- package/es/style/index.css +63 -0
- package/es/style/index.less +73 -0
- package/es/style/raw.d.ts +1 -1
- package/es/style/raw.js +1 -1
- package/es/style/raw.js.map +1 -1
- package/es/tools/flow-path/index.js +0 -1
- package/es/tools/flow-path/index.js.map +1 -1
- package/es/tools/label/Label.d.ts +30 -0
- package/es/tools/label/Label.js +241 -0
- package/es/tools/label/Label.js.map +1 -0
- package/es/tools/label/LabelModel.d.ts +26 -0
- package/es/tools/label/LabelModel.js +86 -0
- package/es/tools/label/LabelModel.js.map +1 -0
- package/es/tools/label/LabelOverlay.d.ts +28 -0
- package/es/tools/label/LabelOverlay.js +161 -0
- package/es/tools/label/LabelOverlay.js.map +1 -0
- package/es/tools/label/algorithm.d.ts +16 -0
- package/es/tools/label/algorithm.js +27 -0
- package/es/tools/label/algorithm.js.map +1 -0
- package/es/tools/label/index.d.ts +59 -0
- package/es/tools/label/index.js +292 -0
- package/es/tools/label/index.js.map +1 -0
- package/es/tools/label/mediumEditor.d.ts +17 -0
- package/es/tools/label/mediumEditor.js +92 -0
- package/es/tools/label/mediumEditor.js.map +1 -0
- package/es/tools/label/utils.d.ts +64 -0
- package/es/tools/label/utils.js +336 -0
- package/es/tools/label/utils.js.map +1 -0
- package/es/tools/snapshot/index.d.ts +107 -11
- package/es/tools/snapshot/index.js +366 -149
- package/es/tools/snapshot/index.js.map +1 -1
- package/es/tools/snapshot/utils.d.ts +35 -0
- package/es/tools/snapshot/utils.js +238 -0
- package/es/tools/snapshot/utils.js.map +1 -0
- package/lib/NodeResize/control/Control.d.ts +3 -3
- package/lib/NodeResize/control/Control.js +13 -3
- package/lib/NodeResize/control/Control.js.map +1 -1
- package/lib/NodeResize/index.d.ts +4 -0
- package/lib/NodeResize/index.js.map +1 -1
- package/lib/NodeResize/node/DiamondResize.d.ts +1 -0
- package/lib/NodeResize/node/DiamondResize.js +2 -1
- package/lib/NodeResize/node/DiamondResize.js.map +1 -1
- package/lib/NodeResize/node/EllipseResize.d.ts +1 -0
- package/lib/NodeResize/node/EllipseResize.js +2 -1
- package/lib/NodeResize/node/EllipseResize.js.map +1 -1
- package/lib/NodeResize/node/HtmlResize.js +1 -1
- package/lib/NodeResize/node/HtmlResize.js.map +1 -1
- package/lib/NodeResize/node/RectResize.js +1 -1
- package/lib/NodeResize/node/RectResize.js.map +1 -1
- package/lib/bpmn/constant.d.ts +1 -1
- package/lib/bpmn/constant.js +3 -0
- package/lib/bpmn/constant.js.map +1 -1
- package/lib/bpmn/index.d.ts +3 -6
- package/lib/bpmn/index.js +5 -7
- package/lib/bpmn/index.js.map +1 -1
- package/lib/bpmn-elements/presets/Pool/Pool.d.ts +21 -1
- package/lib/components/control/index.d.ts +4 -4
- package/lib/components/control/index.js.map +1 -1
- package/lib/components/highlight/index.d.ts +6 -4
- package/lib/components/highlight/index.js +32 -5
- package/lib/components/highlight/index.js.map +1 -1
- package/lib/components/menu/index.d.ts +1 -1
- package/lib/components/menu/index.js +9 -10
- package/lib/components/menu/index.js.map +1 -1
- package/lib/components/mini-map/index.d.ts +1 -1
- package/lib/components/mini-map/index.js +2 -2
- package/lib/components/mini-map/index.js.map +1 -1
- package/lib/components/selection-select/index.d.ts +1 -1
- package/lib/components/selection-select/index.js.map +1 -1
- package/lib/dynamic-group/index.d.ts +106 -0
- package/lib/dynamic-group/index.js +553 -0
- package/lib/dynamic-group/index.js.map +1 -0
- package/lib/dynamic-group/model.d.ts +135 -0
- package/lib/dynamic-group/model.js +416 -0
- package/lib/dynamic-group/model.js.map +1 -0
- package/lib/dynamic-group/node.d.ts +16 -0
- package/lib/dynamic-group/node.js +146 -0
- package/lib/dynamic-group/node.js.map +1 -0
- package/lib/dynamic-group/utils.d.ts +17 -0
- package/lib/dynamic-group/utils.js +32 -0
- package/lib/dynamic-group/utils.js.map +1 -0
- package/lib/index.css +63 -0
- package/lib/index.d.ts +16 -8
- package/lib/index.js +24 -8
- package/lib/index.js.map +1 -1
- package/lib/insert-node-in-polyline/index.js +2 -2
- package/lib/insert-node-in-polyline/index.js.map +1 -1
- package/lib/materials/group/GroupNode.d.ts +6 -10
- package/lib/materials/group/GroupNode.js +8 -6
- package/lib/materials/group/GroupNode.js.map +1 -1
- package/lib/materials/group/index.d.ts +5 -5
- package/lib/materials/group/index.js +24 -25
- package/lib/materials/group/index.js.map +1 -1
- package/lib/materials/node-selection/index.d.ts +6 -1
- package/lib/materials/node-selection/index.js +63 -55
- package/lib/materials/node-selection/index.js.map +1 -1
- package/lib/mindmap/index.d.ts +2 -2
- package/lib/style/index.css +63 -0
- package/lib/style/index.less +73 -0
- package/lib/style/raw.d.ts +1 -1
- package/lib/style/raw.js +1 -1
- package/lib/style/raw.js.map +1 -1
- package/lib/tools/flow-path/index.js +0 -1
- package/lib/tools/flow-path/index.js.map +1 -1
- package/lib/tools/label/Label.d.ts +30 -0
- package/lib/tools/label/Label.js +247 -0
- package/lib/tools/label/Label.js.map +1 -0
- package/lib/tools/label/LabelModel.d.ts +26 -0
- package/lib/tools/label/LabelModel.js +89 -0
- package/lib/tools/label/LabelModel.js.map +1 -0
- package/lib/tools/label/LabelOverlay.d.ts +28 -0
- package/lib/tools/label/LabelOverlay.js +167 -0
- package/lib/tools/label/LabelOverlay.js.map +1 -0
- package/lib/tools/label/algorithm.d.ts +16 -0
- package/lib/tools/label/algorithm.js +32 -0
- package/lib/tools/label/algorithm.js.map +1 -0
- package/lib/tools/label/index.d.ts +59 -0
- package/lib/tools/label/index.js +298 -0
- package/lib/tools/label/index.js.map +1 -0
- package/lib/tools/label/mediumEditor.d.ts +17 -0
- package/lib/tools/label/mediumEditor.js +98 -0
- package/lib/tools/label/mediumEditor.js.map +1 -0
- package/lib/tools/label/utils.d.ts +64 -0
- package/lib/tools/label/utils.js +349 -0
- package/lib/tools/label/utils.js.map +1 -0
- package/lib/tools/snapshot/index.d.ts +107 -11
- package/lib/tools/snapshot/index.js +366 -149
- package/lib/tools/snapshot/index.js.map +1 -1
- package/lib/tools/snapshot/utils.d.ts +35 -0
- package/lib/tools/snapshot/utils.js +247 -0
- package/lib/tools/snapshot/utils.js.map +1 -0
- package/package.json +9 -3
- package/rollup.config.js +1 -1
- package/src/NodeResize/control/Control.tsx +13 -3
- package/src/NodeResize/index.ts +4 -0
- package/src/NodeResize/node/DiamondResize.tsx +2 -1
- package/src/NodeResize/node/EllipseResize.tsx +2 -1
- package/src/NodeResize/node/HtmlResize.tsx +1 -1
- package/src/NodeResize/node/RectResize.tsx +1 -1
- package/src/bpmn/constant.ts +4 -1
- package/src/bpmn/index.ts +7 -4
- package/src/bpmn-elements-adapter/README.md +1 -3
- package/src/components/control/index.ts +4 -4
- package/src/components/highlight/index.ts +33 -6
- package/src/components/menu/index.ts +16 -13
- package/src/components/mini-map/index.ts +3 -3
- package/src/components/selection-select/index.ts +6 -2
- package/src/dynamic-group/index.ts +609 -0
- package/src/dynamic-group/model.ts +503 -0
- package/src/dynamic-group/node.ts +140 -0
- package/src/dynamic-group/utils.ts +33 -0
- package/src/index.ts +30 -8
- package/src/insert-node-in-polyline/index.ts +3 -3
- package/src/materials/group/GroupNode.ts +12 -12
- package/src/materials/group/index.ts +40 -40
- package/src/materials/node-selection/index.ts +78 -70
- package/src/style/index.less +73 -0
- package/src/style/raw.ts +64 -1
- package/src/tools/flow-path/index.ts +0 -1
- package/src/tools/label/Label.tsx +297 -0
- package/src/tools/label/LabelModel.ts +82 -0
- package/src/tools/label/LabelOverlay.tsx +159 -0
- package/src/tools/label/algorithm.ts +42 -0
- package/src/tools/label/index.ts +401 -0
- package/src/tools/label/mediumEditor.ts +94 -0
- package/src/tools/label/utils.ts +395 -0
- package/src/tools/snapshot/README.md +141 -5
- package/src/tools/snapshot/index.ts +288 -101
- package/src/tools/snapshot/utils.ts +163 -0
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
import LogicFlow, { createUuid, GraphModel, TextMode } from '@logicflow/core'
|
|
2
|
+
import { cloneDeep, forEach, isArray, isObject, map } from 'lodash-es'
|
|
3
|
+
import LabelOverlay, { LabelConfigType } from './LabelOverlay'
|
|
4
|
+
|
|
5
|
+
import Position = LogicFlow.Position
|
|
6
|
+
import NodeData = LogicFlow.NodeData
|
|
7
|
+
import EdgeData = LogicFlow.EdgeData
|
|
8
|
+
import Extension = LogicFlow.Extension
|
|
9
|
+
import LabelConfig = LogicFlow.LabelConfig
|
|
10
|
+
import GraphElement = LogicFlow.GraphElement
|
|
11
|
+
import {
|
|
12
|
+
BBoxInfo,
|
|
13
|
+
calcPointAfterResize,
|
|
14
|
+
rotatePointAroundCenter,
|
|
15
|
+
} from './utils'
|
|
16
|
+
|
|
17
|
+
// 类型定义,如果 isMultiple 为 true 的话,maxCount 为数值且大于 1
|
|
18
|
+
export type ILabelOptions = {
|
|
19
|
+
isMultiple?: boolean
|
|
20
|
+
maxCount?: number
|
|
21
|
+
labelWidth?: number
|
|
22
|
+
textOverflowMode?: 'ellipsis' | 'wrap' | 'clip' | 'nowrap' | 'default'
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export class Label implements Extension {
|
|
26
|
+
static pluginName = 'label'
|
|
27
|
+
|
|
28
|
+
lf: LogicFlow
|
|
29
|
+
options: ILabelOptions
|
|
30
|
+
|
|
31
|
+
textOverflowMode: 'ellipsis' | 'wrap' | 'clip' | 'nowrap' | 'default'
|
|
32
|
+
isMultiple: boolean
|
|
33
|
+
labelWidth?: number
|
|
34
|
+
maxCount: number // 默认值给无限大数值
|
|
35
|
+
|
|
36
|
+
labelInitPositionMap: Map<string, Position> = new Map()
|
|
37
|
+
|
|
38
|
+
constructor({ lf, options }: { lf: LogicFlow; options: ILabelOptions }) {
|
|
39
|
+
this.lf = lf
|
|
40
|
+
// DONE: 根据 options 初始化一些插件配置,比如是否支持多个 label 等,生效在所有 label 中
|
|
41
|
+
this.options = options ?? {}
|
|
42
|
+
|
|
43
|
+
this.textOverflowMode = options.textOverflowMode ?? 'default'
|
|
44
|
+
this.isMultiple = options.isMultiple ?? true
|
|
45
|
+
this.labelWidth = options.labelWidth
|
|
46
|
+
this.maxCount = options.maxCount ?? Infinity
|
|
47
|
+
|
|
48
|
+
// DONE: 1. 启用插件时,将当前画布的 textMode 更新为 TextMode.LABEL。
|
|
49
|
+
// 如果将其又重新设置为 TextModel.TEXT,则需要 disable 掉 Label 工具,enable TextEditTool
|
|
50
|
+
lf.graphModel.editConfigModel.updateTextMode(TextMode.LABEL)
|
|
51
|
+
|
|
52
|
+
// TODO: 2. 做一些插件需要的事件监听
|
|
53
|
+
this.addEventListeners()
|
|
54
|
+
|
|
55
|
+
// TODO: 3. 自定义快捷键,比如 delete,选中 label 时,移除 label
|
|
56
|
+
// this.rewriteShortcut()
|
|
57
|
+
|
|
58
|
+
// 插件中注册 LabelOverlay 工具,用于 label 的编辑
|
|
59
|
+
lf.tool.registerTool(LabelOverlay.toolName, LabelOverlay)
|
|
60
|
+
// LabelOverlay 和 TextEditTool 互斥,所以将它 disable 掉
|
|
61
|
+
lf.tool.disableTool('text-edit-tool')
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* 格式化元素的 Label 配置,后续初始化 Label 用统一的数据格式
|
|
66
|
+
* 主要是将 _label 类型 string | LabelConfig | LabelConfig[] 统一转换为 LabelConfig[]
|
|
67
|
+
* @param graphModel 当前图的 model
|
|
68
|
+
* @param element 当前元素 model
|
|
69
|
+
* @return LabelConfig[]
|
|
70
|
+
*/
|
|
71
|
+
private formatConfig(
|
|
72
|
+
graphModel: GraphModel,
|
|
73
|
+
element: GraphElement,
|
|
74
|
+
): LabelConfig[] {
|
|
75
|
+
const {
|
|
76
|
+
editConfigModel: {
|
|
77
|
+
nodeTextEdit,
|
|
78
|
+
edgeTextEdit,
|
|
79
|
+
nodeTextDraggable,
|
|
80
|
+
edgeTextDraggable,
|
|
81
|
+
},
|
|
82
|
+
} = graphModel
|
|
83
|
+
const { textOverflowMode, isMultiple, maxCount, labelWidth } = this
|
|
84
|
+
const {
|
|
85
|
+
text,
|
|
86
|
+
zIndex,
|
|
87
|
+
properties: { _label, _labelOption = {} },
|
|
88
|
+
} = element
|
|
89
|
+
|
|
90
|
+
// 当前元素的 Label 相关配置
|
|
91
|
+
const curLabelConfig = _label as LabelConfigType
|
|
92
|
+
const { isMultiple: curIsMultiple, maxCount: curMaxCount }: ILabelOptions =
|
|
93
|
+
_labelOption as ILabelOptions
|
|
94
|
+
|
|
95
|
+
// REMIND: 对 3 种可能得数据类型进行处理
|
|
96
|
+
let formatConfig: LabelConfig[] = [] // 保存格式化后的 LabelConfig
|
|
97
|
+
if (isArray(curLabelConfig)) {
|
|
98
|
+
// 1. 数组的话就是 LabelConfig[] 类型
|
|
99
|
+
// 判断是否开启 isMultiple, 如果开启了,判断是否超过最大数量。超出就截取
|
|
100
|
+
const size = curMaxCount ?? maxCount // 优先级,当设置 multiple 时,元素的 maxCount 优先级高于插件的 maxCount
|
|
101
|
+
if (isMultiple && curIsMultiple) {
|
|
102
|
+
if (curLabelConfig.length > size) {
|
|
103
|
+
formatConfig = curLabelConfig.slice(0, size)
|
|
104
|
+
} else {
|
|
105
|
+
formatConfig = curLabelConfig
|
|
106
|
+
}
|
|
107
|
+
} else {
|
|
108
|
+
formatConfig = [curLabelConfig[0]]
|
|
109
|
+
}
|
|
110
|
+
} else if (isObject(curLabelConfig)) {
|
|
111
|
+
// 2. 对象的话就是 LabelConfig 类型
|
|
112
|
+
formatConfig = [curLabelConfig]
|
|
113
|
+
} else if (typeof curLabelConfig === 'string' || !curLabelConfig) {
|
|
114
|
+
// 3. 字符串或者为空的话就是 string 类型,基于 text 的数据合成 LabelConfig 信息(主要复用 text 的 x,y 信息)
|
|
115
|
+
const config: LabelConfig = {
|
|
116
|
+
...text,
|
|
117
|
+
content: curLabelConfig || text.value,
|
|
118
|
+
draggable:
|
|
119
|
+
element.BaseType === 'edge' ? edgeTextDraggable : nodeTextDraggable,
|
|
120
|
+
}
|
|
121
|
+
formatConfig = config.value ? [config] : []
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// TODO: 针对 Edge,在 edge 更新时 重新计算 Label 的位置
|
|
125
|
+
if (element.BaseType === 'edge') {
|
|
126
|
+
// 判断当前 label,是否在 edge 的路径上,如果不在,就重新计算位置
|
|
127
|
+
formatConfig = map(formatConfig, (config) => {
|
|
128
|
+
const { x, y } = config
|
|
129
|
+
console.log('x, y --->>>', x, y)
|
|
130
|
+
|
|
131
|
+
return config
|
|
132
|
+
})
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// DONE: 再根据一些全局配置,比如是否支持垂直显示等,对 LabelConfig 进行二次处理
|
|
136
|
+
// 优先级:全局配置 > 元素配置。比如全局设置 isMultiple 为 true 时,才可以使用 局部的 isMultiple 设置才生效
|
|
137
|
+
// 当全局 isMultiple 为 false 时,局部的 isMultiple 不生效
|
|
138
|
+
return map(formatConfig, (config) => {
|
|
139
|
+
if (!config.id) {
|
|
140
|
+
config.id = createUuid()
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const {
|
|
144
|
+
value,
|
|
145
|
+
content,
|
|
146
|
+
vertical,
|
|
147
|
+
editable,
|
|
148
|
+
draggable,
|
|
149
|
+
textOverflowMode: labelTextOverflowMode,
|
|
150
|
+
} = config
|
|
151
|
+
|
|
152
|
+
const textEdit = element.BaseType === 'node' ? nodeTextEdit : edgeTextEdit
|
|
153
|
+
const textDraggable =
|
|
154
|
+
element.BaseType === 'node' ? nodeTextDraggable : edgeTextDraggable
|
|
155
|
+
|
|
156
|
+
return {
|
|
157
|
+
...config,
|
|
158
|
+
zIndex,
|
|
159
|
+
labelWidth,
|
|
160
|
+
content: content ?? value,
|
|
161
|
+
vertical: vertical ?? false,
|
|
162
|
+
editable: textEdit && editable,
|
|
163
|
+
draggable: textDraggable && draggable,
|
|
164
|
+
textOverflowMode: labelTextOverflowMode ?? textOverflowMode,
|
|
165
|
+
}
|
|
166
|
+
})
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* 根据初始化的数据,格式化 Label 的数据格式后,统一更新到元素的 properties._label 中,保证后续的渲染以这个数据格式进行
|
|
171
|
+
* @param graphModel
|
|
172
|
+
*/
|
|
173
|
+
private setupLabels(graphModel: GraphModel) {
|
|
174
|
+
// const elements = [...graphModel.nodes, ...graphModel.edges]
|
|
175
|
+
const elements = graphModel.sortElements
|
|
176
|
+
|
|
177
|
+
// TODO: 1. 筛选出当前画布上,textMode 为 TextMode.LABEL 的元素(在支持元素级别的 textMode 时,需要做这个筛选)
|
|
178
|
+
// REMIND: 本期先只支持全局配置,所以判断全局的 textMode 即可
|
|
179
|
+
forEach(elements, (element) => {
|
|
180
|
+
// DONE: 2. 在此处做数据的转换
|
|
181
|
+
// 输入:NodeConfig.properties._label: string | LabelConfig | LabelConfig[]
|
|
182
|
+
// 输出:NodeData.properties._label: LabelData | LabelData[]
|
|
183
|
+
// 是否需要根据 isMultiple 控制是否返回数组或对象 or 直接全部返回数组 ❓❓❓ -> 目前直接全部返回数组
|
|
184
|
+
|
|
185
|
+
this.rewriteInnerMethods(element)
|
|
186
|
+
|
|
187
|
+
const formatLabelConfig = this.formatConfig(graphModel, element)
|
|
188
|
+
// FIX: BUG Here: 格式化后的 labelConfig 没有同步到 element 上,导致每次重新渲染时,都会重新格式化,且重新生成 id
|
|
189
|
+
// 但如果在此处通过 setProperty 更新元素的 _label 时,又会导致死循环
|
|
190
|
+
element.setProperty('_label', formatLabelConfig)
|
|
191
|
+
})
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* 给元素添加一个 label
|
|
196
|
+
* @param element
|
|
197
|
+
* @param position
|
|
198
|
+
*/
|
|
199
|
+
private addLabel(element: GraphElement, position: Position) {
|
|
200
|
+
const { maxCount } = this
|
|
201
|
+
const {
|
|
202
|
+
properties: { _label, _labelOption },
|
|
203
|
+
} = element
|
|
204
|
+
const curLabelConfig = (_label as LabelConfig[]) ?? []
|
|
205
|
+
const curLabelOption = (_labelOption as ILabelOptions) ?? {}
|
|
206
|
+
|
|
207
|
+
const len = curLabelConfig.length
|
|
208
|
+
const newLabel = {
|
|
209
|
+
id: createUuid(),
|
|
210
|
+
x: position.x,
|
|
211
|
+
y: position.y,
|
|
212
|
+
content: `Label${len + 1}`,
|
|
213
|
+
value: `Label${len + 1}`,
|
|
214
|
+
style: {},
|
|
215
|
+
draggable: true,
|
|
216
|
+
editable: true,
|
|
217
|
+
vertical: false,
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if (len >= (curLabelOption?.maxCount ?? maxCount)) {
|
|
221
|
+
return
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
curLabelConfig.push(newLabel)
|
|
225
|
+
element.setProperty('_label', curLabelConfig)
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* 移除元素的某个 label
|
|
230
|
+
* @private
|
|
231
|
+
*/
|
|
232
|
+
// private removeLabel() {}
|
|
233
|
+
|
|
234
|
+
private addEventListeners() {
|
|
235
|
+
const { graphModel } = this.lf
|
|
236
|
+
const { eventCenter, editConfigModel } = graphModel
|
|
237
|
+
|
|
238
|
+
eventCenter.on('graph:rendered', ({ graphModel }) => {
|
|
239
|
+
this.setupLabels(graphModel)
|
|
240
|
+
})
|
|
241
|
+
|
|
242
|
+
// 监听元素双击事件,给元素增加 Label
|
|
243
|
+
eventCenter.on(
|
|
244
|
+
'node:dbclick,edge:dbclick',
|
|
245
|
+
({ e, data }: { e: MouseEvent; data: NodeData | EdgeData }) => {
|
|
246
|
+
// DONE: 增加 label 的数据信息到 element model
|
|
247
|
+
const target: GraphElement | undefined = graphModel.getElement(data.id)
|
|
248
|
+
// DONE: 将 clientX 和 clientY 转换为画布坐标
|
|
249
|
+
const {
|
|
250
|
+
canvasOverlayPosition: { x: x1, y: y1 },
|
|
251
|
+
} = graphModel.getPointByClient({
|
|
252
|
+
x: e.clientX,
|
|
253
|
+
y: e.clientY,
|
|
254
|
+
})
|
|
255
|
+
|
|
256
|
+
const point: Position = {
|
|
257
|
+
x: x1,
|
|
258
|
+
y: y1,
|
|
259
|
+
}
|
|
260
|
+
if (target && editConfigModel.textMode === TextMode.LABEL) {
|
|
261
|
+
this.addLabel(target, point)
|
|
262
|
+
}
|
|
263
|
+
},
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
// 监听 node:resize 事件,在 resize 时,重新计算 label 的位置信息
|
|
267
|
+
eventCenter.on('node:resize', ({ preData, data, model }) => {
|
|
268
|
+
const {
|
|
269
|
+
width: preWidth,
|
|
270
|
+
height: preHeight,
|
|
271
|
+
_label = [],
|
|
272
|
+
} = preData.properties ?? {}
|
|
273
|
+
const { width: curWidth, height: curHeight } = data.properties ?? {}
|
|
274
|
+
|
|
275
|
+
if (preWidth && preHeight && curWidth && curHeight) {
|
|
276
|
+
const origin: BBoxInfo = {
|
|
277
|
+
x: preData.x,
|
|
278
|
+
y: preData.y,
|
|
279
|
+
width: preWidth,
|
|
280
|
+
height: preHeight,
|
|
281
|
+
}
|
|
282
|
+
const scaled: BBoxInfo = {
|
|
283
|
+
x: data.x,
|
|
284
|
+
y: data.y,
|
|
285
|
+
width: curWidth,
|
|
286
|
+
height: curHeight,
|
|
287
|
+
}
|
|
288
|
+
const newLabelConfig = map(_label as LabelConfig[], (label) => {
|
|
289
|
+
const { x, y } = label
|
|
290
|
+
const newPoint = calcPointAfterResize(origin, scaled, { x, y })
|
|
291
|
+
return {
|
|
292
|
+
...label,
|
|
293
|
+
...newPoint,
|
|
294
|
+
}
|
|
295
|
+
})
|
|
296
|
+
|
|
297
|
+
model.setProperty('_label', newLabelConfig)
|
|
298
|
+
}
|
|
299
|
+
})
|
|
300
|
+
|
|
301
|
+
// 监听 node:rotate 事件,在 rotate 时,重新计算 Label 的位置信息
|
|
302
|
+
eventCenter.on('node:rotate', ({ model }) => {
|
|
303
|
+
const {
|
|
304
|
+
x,
|
|
305
|
+
y,
|
|
306
|
+
rotate,
|
|
307
|
+
properties: { _label = [] },
|
|
308
|
+
} = model
|
|
309
|
+
const center: Position = { x, y }
|
|
310
|
+
|
|
311
|
+
const newLabelConfig = map(_label as LabelConfig[], (label) => {
|
|
312
|
+
if (!label.id) return label
|
|
313
|
+
|
|
314
|
+
let point: Position = { x: label.x, y: label.y }
|
|
315
|
+
if (this.labelInitPositionMap.has(label.id)) {
|
|
316
|
+
point = this.labelInitPositionMap.get(label.id)!
|
|
317
|
+
} else {
|
|
318
|
+
this.labelInitPositionMap.set(label.id, point)
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// 弧度转角度
|
|
322
|
+
let theta = rotate * (180 / Math.PI)
|
|
323
|
+
if (theta < 0) theta += 360
|
|
324
|
+
const radian = theta * (Math.PI / 180)
|
|
325
|
+
|
|
326
|
+
const newPoint = rotatePointAroundCenter(point, center, radian)
|
|
327
|
+
return {
|
|
328
|
+
...label,
|
|
329
|
+
...newPoint,
|
|
330
|
+
rotate: theta,
|
|
331
|
+
}
|
|
332
|
+
})
|
|
333
|
+
|
|
334
|
+
model.setProperty('_label', newLabelConfig)
|
|
335
|
+
})
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* 重写元素的一些方法,以支持 Label 的拖拽、编辑等
|
|
340
|
+
* @param element
|
|
341
|
+
*/
|
|
342
|
+
private rewriteInnerMethods(element: GraphElement) {
|
|
343
|
+
// 重写 edgeModel/nodeModel moveText 方法,在 move text 时,以相同的逻辑移动 label
|
|
344
|
+
element.moveText = (deltaX: number, deltaY: number) => {
|
|
345
|
+
if (!element.text) return
|
|
346
|
+
const {
|
|
347
|
+
text: { x, y, value, draggable, editable },
|
|
348
|
+
} = element
|
|
349
|
+
|
|
350
|
+
element.text = {
|
|
351
|
+
value,
|
|
352
|
+
editable,
|
|
353
|
+
draggable,
|
|
354
|
+
x: x + deltaX,
|
|
355
|
+
y: y + deltaY,
|
|
356
|
+
}
|
|
357
|
+
const properties = cloneDeep(element.getProperties())
|
|
358
|
+
// 重新计算新的 label 位置信息
|
|
359
|
+
if (isArray(properties._label)) {
|
|
360
|
+
const nextLabel = map(properties._label as LabelConfig[], (label) => {
|
|
361
|
+
return {
|
|
362
|
+
...label,
|
|
363
|
+
x: label.x + deltaX,
|
|
364
|
+
y: label.y + deltaY,
|
|
365
|
+
}
|
|
366
|
+
})
|
|
367
|
+
// console.log('Label --->>>', nextLabel)
|
|
368
|
+
element?.setProperty('_label', nextLabel)
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// TODO: others methods ???
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// private rewriteShortcut() {}
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* 更新当前渲染使用的 Text or Label 模式
|
|
379
|
+
*/
|
|
380
|
+
updateTextMode(textMode: TextMode) {
|
|
381
|
+
const {
|
|
382
|
+
graphModel: { editConfigModel },
|
|
383
|
+
} = this.lf
|
|
384
|
+
if (textMode === editConfigModel.textMode) return
|
|
385
|
+
|
|
386
|
+
editConfigModel.updateTextMode(textMode)
|
|
387
|
+
if (textMode === TextMode.LABEL) {
|
|
388
|
+
this.lf.tool.enableTool(LabelOverlay.toolName)
|
|
389
|
+
this.lf.tool.disableTool('text-edit-tool')
|
|
390
|
+
} else if (textMode === TextMode.TEXT) {
|
|
391
|
+
this.lf.tool.enableTool('text-edit-tool')
|
|
392
|
+
this.lf.tool.disableTool(LabelOverlay.toolName)
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
render() {}
|
|
397
|
+
|
|
398
|
+
destroy() {}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
export default Label
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import MediumEditor from 'medium-editor'
|
|
2
|
+
import Picker from 'vanilla-picker'
|
|
3
|
+
import rangy from 'rangy'
|
|
4
|
+
import 'rangy/lib/rangy-classapplier'
|
|
5
|
+
|
|
6
|
+
export const defaultOptions = {
|
|
7
|
+
toolbar: {
|
|
8
|
+
allowMultiParagraphSelection: true,
|
|
9
|
+
buttons: [
|
|
10
|
+
'bold',
|
|
11
|
+
'colorpicker',
|
|
12
|
+
'italic',
|
|
13
|
+
'underline',
|
|
14
|
+
'strikethrough',
|
|
15
|
+
'quote',
|
|
16
|
+
'justifyLeft',
|
|
17
|
+
'justifyCenter',
|
|
18
|
+
'justifyRight',
|
|
19
|
+
'justifyFull',
|
|
20
|
+
'superscript',
|
|
21
|
+
'subscript',
|
|
22
|
+
'orderedlist',
|
|
23
|
+
'unorderedlist',
|
|
24
|
+
'pre',
|
|
25
|
+
'removeFormat',
|
|
26
|
+
'outdent',
|
|
27
|
+
'indent',
|
|
28
|
+
'h2',
|
|
29
|
+
'h3',
|
|
30
|
+
],
|
|
31
|
+
standardizeSelectionStart: false,
|
|
32
|
+
updateOnEmptySelection: false,
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
placeholder: {
|
|
36
|
+
text: '请输入内容',
|
|
37
|
+
hideOnClick: true,
|
|
38
|
+
},
|
|
39
|
+
disableEditing: true,
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export const ColorPickerButton = MediumEditor.extensions.button.extend({
|
|
43
|
+
name: 'colorpicker',
|
|
44
|
+
tagNames: ['mark'],
|
|
45
|
+
contentDefault: '<b>Color</b>',
|
|
46
|
+
aria: 'Color Picker',
|
|
47
|
+
action: 'colorPicker',
|
|
48
|
+
init: function () {
|
|
49
|
+
rangy.init()
|
|
50
|
+
MediumEditor.extensions.button.prototype.init.call(this)
|
|
51
|
+
this.colorPicker = new Picker({
|
|
52
|
+
parent: this.button,
|
|
53
|
+
color: '#000',
|
|
54
|
+
onDone: (res) => {
|
|
55
|
+
if (this.coloredText && this.coloredText.isAppliedToSelection()) {
|
|
56
|
+
this.coloredText.undoToSelection()
|
|
57
|
+
}
|
|
58
|
+
this.coloredText = rangy.createClassApplier('colored', {
|
|
59
|
+
elementTagName: 'span',
|
|
60
|
+
elementProperties: {
|
|
61
|
+
style: {
|
|
62
|
+
color: res.hex,
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
normalize: true,
|
|
66
|
+
})
|
|
67
|
+
this.coloredText.toggleSelection()
|
|
68
|
+
this.base.checkContentChanged()
|
|
69
|
+
this.setInactive()
|
|
70
|
+
},
|
|
71
|
+
})
|
|
72
|
+
},
|
|
73
|
+
getButton: function () {
|
|
74
|
+
return this.button
|
|
75
|
+
},
|
|
76
|
+
handleClick: function () {
|
|
77
|
+
this.setActive()
|
|
78
|
+
this.colorPicker.show()
|
|
79
|
+
},
|
|
80
|
+
isAlreadyApplied: function (node) {
|
|
81
|
+
return node.nodeName.toLowerCase() === 'mark'
|
|
82
|
+
},
|
|
83
|
+
isActive: function () {
|
|
84
|
+
return this.button.classList.contains('medium-editor-button-active')
|
|
85
|
+
},
|
|
86
|
+
setInactive: function () {
|
|
87
|
+
this.button.classList.remove('medium-editor-button-active')
|
|
88
|
+
},
|
|
89
|
+
setActive: function () {
|
|
90
|
+
this.button.classList.add('medium-editor-button-active')
|
|
91
|
+
},
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
export { MediumEditor }
|