Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(core&extension):边与节点文本逻辑优化 #1672

Closed
wants to merge 8 commits into from

Conversation

DymoneLewis
Copy link
Collaborator

feat(extension): 新增Label文本模式,支持配置多文本和修改文本朝向
feat(core): 增加label文本相关逻辑&新增折线边和贝塞尔曲线边文本位置计算算法

Copy link

changeset-bot bot commented Jul 10, 2024

⚠️ No Changeset found

Latest commit: fcb0543

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@@ -32,6 +32,7 @@
"eslint": "^8.45.0",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.3",
"medium-editor": "^5.23.3",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mark 一下,删掉

x: 300,
y: 150,
value: '11111',
verticle: true,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mark

@@ -151,6 +262,7 @@ export default function BasicNode() {
// adjustEdge: false,
allowRotate: true,
edgeTextEdit: true,
nodeTextVerticle: true,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

考虑一下是否更名 nodeLabelVertical,不然 nodeText 会有冲突

@@ -201,7 +315,7 @@ export default function BasicNode() {
registerElements(lf)
// 注册事件
registerEvents(lf)

// lf.extension.selectionSelect.__disabled = true;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mark remove

content?: string // label html的内容,PS:value是label的纯文本内容
} & TextConfig

export type LabelConfig = {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LabelOptions

@@ -1437,6 +1435,33 @@ export namespace LogicFlow {
draggable?: boolean
} & Position

// label数据类型声明
export type LabelType = {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LabelConfig

LabelData

export type LabelType = {
id?: string // label唯一标识
relateId?: string // 关联节点/关联边的id
minWidth?: string | null // label最小宽度
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NumberOrPercent

maxWidth?: string | null // label最大宽度
minHeight?: string | null // label最小高度
maxHeight?: string | null // label最大高度
style?: object // label自定义样式
Copy link
Collaborator

@boyongjiong boyongjiong Jul 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SVG -> LogicFlow.ComonTheme
HTML -> h.JSX.CSSProperties

maxHeight?: string | null // label最大高度
style?: object // label自定义样式
virtical?: boolean // 是否渲染纵向文本
isFocus?: boolean // label是否获焦
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

可以暂时不支持,等到有具体需求的时候,我们再考虑加进来

因为我感觉这个是内部运营状态,初始化设置值有点奇怪

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • isFocus
  • isHover
  • isInLine

yDeltaDistance?: number // label在x轴上相对节点/边的偏移距离
xDeltaDistance?: number // label在y轴上相对节点/边的偏移距离
content?: string // label html的内容,PS:value是label的纯文本内容
} & TextConfig
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mark 一下

zIndex?: number
properties?: PropertiesType
virtual?: boolean // 是否虚拟节点
rotate?: number
textMode?: string
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'label' | 'text'

})
return result
}
const { minX, minY, maxX, maxY } = result as any
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

可以参考 NodeBBox 类型定义,minX, minY, maxX, maxY 提出类型定义,方便复用

在此处使用这个类型定义

return getDistance(point, segmentStart)
}
// 计算边外点在线段上的投影点
const t =
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

如果可能得话,可以把数学公式 wiki 或者名字写一下,但不重要,就是好奇

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

可能是因为太简单了这个公式没有名字

@@ -125,3 +141,8 @@ export enum SegmentDirection {
HORIZONTAL = 'horizontal',
VERTICAL = 'vertical',
}

export enum TextMode {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remind: 统一

@@ -206,6 +207,7 @@ export namespace Model {

getData: () => Record<string, unknown>
getProperties: () => PropertyType
getTextShape: () => HTMLElement | null
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remind rename -> getLabelShape

@@ -87,6 +88,10 @@ export interface EditConfigInterface {
* 不支持ctrl,ctrl会触发contextmenu
*/
multipleSelectKey?: string
// 节点文本类型
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remind: 同步增加下面 editConfig 中的 options

@@ -151,6 +158,12 @@ export class EditConfigModel {
@observable nodeTextDraggable = false
@observable edgeTextDraggable = false
@observable autoExpand = false
@observable multipleNodeText = false // 是否支持多个节点文本
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

后面可以做个分类,添加一些注释

edgeModel.moveText(x1 - x, y1 - y)
return
}
if (edgeModel.modelType === ModelType.POLYLINE_EDGE) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍🏻

content: '',
}
@observable label: LabelType[] = []
@observable properties: Record<string, unknown> = {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remind:看 properties 是否还需要赋值

* @overridable 支持重写
* 获取当前节点文本内容
*/
getTextShape() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remind

...getEdgeLabelDeltaOfBbox(item, this.pointsList),
isInLine:
this.modelType === ModelType.BEZIER_EDGE
? isPointInBezier(item, this.pointsList, 20)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

确认一下 这两个类似的方法,参数统一

@@ -1,9 +1,11 @@
import { cloneDeep } from 'lodash-es'
import { cloneDeep, reduce, max } from 'lodash-es'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TextNodeModel 还原成之前的样式

@@ -254,3 +254,69 @@
.lf-resize-control-w {
cursor: w-resize;
}

.lf-label-overlay {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remind:先移到 extension 中

@@ -0,0 +1,376 @@
import { Component } from 'preact/compat'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remind:remove

edgeModel.setText(
Object.assign({}, edgeModel.text, edgeModel.textPosition),
)
}
// 如果textMode === TEXT
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

如果 textMode === LABEL

edgeModel.setText(
Object.assign({}, edgeModel.text, edgeModel.textPosition),
)
}
// 如果textMode === TEXT
if (
edgeModel.textMode === TextMode.TEXT &&
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

同上

if (editConfigModel.edgeTextEdit && model.text.editable) {
graphModel.setElementStateById(model.id, ElementState.TEXT_EDIT)
if (
(editConfigModel.edgeTextEdit && textMode === TextMode.LABEL) ||
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mark 确认一下逻辑

type: 'rect',
x: 600,
y: 300,
textMode: 'label',
label: ['22221', '22222', '22223'],
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. 讨论如果是插件添加的数据,应该放在哪儿比较合理?

直接在 NodeData 中加字段?还是在 properties 中增加

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Symbol() 或者 _label . 方便解耦

暂时结论:

  1. 以后 extension 中新增的数据,都放到 properties
  2. 确认放到 properties 里面会不会有什么问题

textMode: 'label',
label: ['22221', '22222', '22223'],
properties: {
LabelOptions: {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. LabelOptions 这个为什么要用 大驼峰 0.o
  2. LabelOptions 放在哪儿比较合适?
  3. 如果 properties 中增加 label 和 labelOptions 字段,用于 Label 插件使用

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

结论:
插件的属性或配置项以 _${插件名小驼峰}${自定义属性名称 大驼峰}

// 会去影响我们 graphData 里面的数据的
{
    _labelData // extension 的数据
    _labelOptions // extension 的配置
}

node-selection
_nodeSelectionIds
properties._nodeSelectionO: { Ids }

group

// 纯工具类的,不会影响 graphData
_miniMap : {}
_miniMapOptions

{
  label: {
    data,
    options,
  }
}

sourceNodeId: 'custom-node-3',
targetNodeId: 'custom-node-5',
type: 'bezier',
textMode: 'label',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

textMode 是否要提供节点或边级别的控制粒度,是否直接通过 new LogicFlow 时options 提供 textMode 就行。

内部逻辑是否就可以不那么动态

-> options.labelOptions.textMode

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new LogicFlow({
  plugins: [Label]
})

lf.editConfigModel.textMode === 'text'

  1. 全局配置:默认用的 editConfigModel -> textMode: 'label'

渲染节点或者边的时候,默认就用 label

  1. 如果元素的 Config 中 properties._labelConfig.textMode = 'text' | 'label'

问题:什么时机去设置 textMode 这个状态值呢 -> plugin 的 init 方法中

@@ -157,6 +252,7 @@ export default function BasicNode() {
allowRotate: true,
// allowResize: true,
edgeTextEdit: true,
nodeLabelVerticle: true,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

verticle 这种属性是否可以通过 style 的方式设置

目前有几种可能得设置方式:

  1. 全局 options
  2. 节点 properties 中 labelOptions
  3. 节点中 labelStyle

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PluginOptions: {
  Label: {
    nodeLabelVertical,
    edgeLabelVertical
    // ...
  }
}

// TODO: 2. review 一下本函数代码逻辑,确认 nodeIdMap 的作用,看是否有优化的空间
console.log('distance', distance)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

手动狗头

}
},
{
minX: Infinity,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

review 一下 minX minY maxX maxY 的赋值逻辑

@@ -9,7 +11,13 @@ let selected: LogicFlow.GraphData | null = null
function translationNodeData(nodeData: NodeData, distance: number) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

通过事件的方式联动,目前这种会有代码耦合的问题

因为目前本来 core 包是没有 label 这个概念的

maxHeight?: string | null // label最大高度
style?: object // label自定义样式
virtical?: boolean // 是否渲染纵向文本
isFocus?: boolean // label是否获焦
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • isFocus
  • isHover
  • isInLine

}
}
}
if (this.textMode === TextMode.LABEL && isArray(this.label)) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

在 label 更新时直接通过 setProperties 的方式,将 label 的数据写入 element 的 properties 中,方便最后 getData 使用,与内部方法解耦

/**
* 移动边上的文本
*/
@action moveLabel(deltaX, deltaY, labelId?: string): void {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

通过事件的方式解耦

在 label 内部监听 NodeMove or EdgeMove 事件,根据回调中的 deltaX/deltaY 等重新计算 label 的位置信息

@@ -31,7 +49,16 @@ function translationEdgeData(edgeData: EdgeData, distance: number) {
point.y += distance
})
}
if (edgeData.text) {
if (graph.useLabelText(edgeData)) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's this?

nodeData.text.x += distance
nodeData.text.y += distance
}
graph.eventCenter.emit(EventType.LABEL_SHOULD_UPDATE, {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

是不是每次 translate 都要触发这个事件,这儿是不是 要加 TEXT_SHOULD_UPDATE 事件

y1: number // Left Top Y
x2: number // Right Bottom X
y2: number // Right Bottom Y
minX: number // Left Top X
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mark 一下,因为这个变量是 抛出去的,在一些插件中用了,所以下面得确认一下是否都改过来了

@@ -765,6 +771,14 @@ export class GraphModel {
node.text.x += node.x - nodeX
node.text.y += node.y - nodeY
}
this.eventCenter.emit(EventType.LABEL_SHOULD_UPDATE, {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review 一下这些事件触发的时机

y1: this.y - this.height / 2,
x2: this.x + this.width / 2,
y2: this.y + this.height / 2,
minX: this.x - this.width / 2,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个改动稍微有点危险,因为这是个公共方法,很多自定义节点可能都会去重写这个方法

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants