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

fix: 修复一系列Label插件问题 #1969

Merged
merged 10 commits into from
Nov 26, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,9 @@ export default function BasicNode() {
const lf = new LogicFlow({
...config,
container: containerRef.current as HTMLElement,
keyboard: {
enabled: true,
},
// container: document.querySelector('#graph') as HTMLElement,
plugins: [Label, DndPanel],
pluginsOptions: {
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/LogicFlow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1451,6 +1451,7 @@ export namespace LogicFlow {
// label数据类型声明
export type LabelConfig = {
id?: string // label唯一标识
type?: string
x: number
y: number
content?: string // 富文本内容
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/view/node/BaseNode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ export abstract class BaseNode<P extends IProps = IProps> extends Component<
// 不是双击的,默认都是单击
if (isDoubleClick) {
if (editConfigModel.nodeTextEdit) {
if (model.text.editable) {
if (model.text.editable && editConfigModel.textMode === TextMode.TEXT) {
model.setSelected(false)
graphModel.setElementStateById(model.id, ElementState.TEXT_EDIT)
}
Expand Down
8 changes: 3 additions & 5 deletions packages/extension/src/style/index.less
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,12 @@
}

&-editing {
border: 2px solid #275dc5;
outline: none;
outline: 2px solid #275dc5;
Copy link
Collaborator

Choose a reason for hiding this comment

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

see see

cursor: text;
}

&-hover {
border: 2px dashed #acacac;
outline: 2px dashed #acacac;
}

// textOverflowMode
Expand All @@ -57,13 +56,11 @@
}

&-wrap {
width: 100px; /* 根据需要调整宽度 */
white-space: normal;
overflow-wrap: break-word; /* 允许单词内换行 */
}

&-nowrap {
width: 100px; /* 根据需要调整宽度 */
overflow: visible;
white-space: nowrap;
}
Expand Down Expand Up @@ -179,6 +176,7 @@
/* dndpanel */
.lf-dndpanel {
position: absolute;
z-index: 999;
margin: 5px;
padding: 15px 5px;
background: rgb(255 255 255 / 80%);
Expand Down
10 changes: 3 additions & 7 deletions packages/extension/src/style/raw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,11 @@ export const content = `@import url('medium-editor/dist/css/medium-editor.min.cs
cursor: move;
}
.lf-label-overlay .lf-label-editor-editing {
border: 2px solid #275dc5;
outline: none;
outline: 2px solid #275dc5;
cursor: text;
}
.lf-label-overlay .lf-label-editor-hover {
border: 2px dashed #acacac;
outline: 2px dashed #acacac;
}
.lf-label-overlay .lf-label-editor-clip {
width: 100px;
Expand All @@ -55,15 +54,11 @@ export const content = `@import url('medium-editor/dist/css/medium-editor.min.cs
text-overflow: ellipsis;
}
.lf-label-overlay .lf-label-editor-wrap {
width: 100px;
/* 根据需要调整宽度 */
white-space: normal;
overflow-wrap: break-word;
/* 允许单词内换行 */
}
.lf-label-overlay .lf-label-editor-nowrap {
width: 100px;
/* 根据需要调整宽度 */
overflow: visible;
white-space: nowrap;
}
Expand Down Expand Up @@ -159,6 +154,7 @@ export const content = `@import url('medium-editor/dist/css/medium-editor.min.cs
/* dndpanel */
.lf-dndpanel {
position: absolute;
z-index: 999;
margin: 5px;
padding: 15px 5px;
background: rgba(255, 255, 255, 0.8);
Expand Down
161 changes: 106 additions & 55 deletions packages/extension/src/tools/label/Label.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export interface ILabelState {
isEditing: boolean
isHovered: boolean
isDragging: boolean
isSelected: boolean
}

@observer
Expand Down Expand Up @@ -52,6 +53,7 @@ export class Label extends Component<ILabelProps, ILabelState> {
isEditing: false,
isHovered: false,
isDragging: false,
isSelected: false,
}
}

Expand All @@ -75,35 +77,34 @@ export class Label extends Component<ILabelProps, ILabelState> {
const {
editConfigModel: { nodeTextDraggable },
} = graphModel

// 当 label 允许拖拽 且不处于拖拽状态时, StepDrag 开启拖拽
if ((label.draggable ?? nodeTextDraggable) && !this.state.isDragging) {
this.setState({ isDragging: true })
// 当 label 允许拖拽 且不处于拖拽状态、不处于编辑状态时, StepDrag 开启拖拽
if (
(label.draggable ?? nodeTextDraggable) &&
!this.state.isDragging &&
!this.state.isEditing
) {
this.stepDrag.handleMouseDown(e)
}
}
handleMouseUp = (e: MouseEvent) => {
if (this.state.isDragging) {
this.stepDrag.handleMouseUp(e)
}
}
handleDragging = ({ deltaX, deltaY }: IDragParams) => {
const { label, element, graphModel } = this.props
if (!this.state.isDragging) {
this.setState({ isDragging: true })
}
const { label, graphModel } = this.props

// DONE: 添加缩放时拖拽的逻辑,对 deltaX 和 deltaY 进行按比例缩放
const { transformModel } = graphModel
const [curDeltaX, curDeltaY] = transformModel.fixDeltaXY(deltaX, deltaY)

// DONE:更新 label 位置,触发 LABEL:DRAG 事件,并抛出相关的数据
const {
properties: { _label },
} = element
const elementLabel = _label as LabelConfig[]
const idx = findIndex(elementLabel, (cur) => cur.id === label.id)

const target = elementLabel[idx]
elementLabel[idx] = {
...target,
x: target.x + curDeltaX,
y: target.y + curDeltaY,
}
const targetElem = graphModel.getElement(element.id)
targetElem?.setProperty('_label', elementLabel)
this.setElementModelLabelInfo({
x: label.x + curDeltaX,
y: label.y + curDeltaY,
})

graphModel.eventCenter.emit('label:drag', {
data: label.getData(),
Expand All @@ -114,6 +115,21 @@ export class Label extends Component<ILabelProps, ILabelState> {
this.setState({ isDragging: false })
}

handleClick = (e: MouseEvent) => {
const { label, element, graphModel } = this.props
// 更新当前Label选中状态
element.setSelected(!this.state.isSelected)
this.setState({ isSelected: !this.state.isSelected })
this.setElementModelLabelInfo({
isSelected: true,
})
graphModel.eventCenter.emit('label:click', {
data: label.getData(),
e,
model: element,
})
}

handleDbClick = (e: MouseEvent) => {
const { label, element, graphModel } = this.props
graphModel.eventCenter.emit('label:dblclick', {
Expand Down Expand Up @@ -162,9 +178,28 @@ export class Label extends Component<ILabelProps, ILabelState> {
this.setState({
isDragging: false,
isHovered: false,
isSelected: false,
})
}

setElementModelLabelInfo(data) {
const { label, element, graphModel } = this.props
const {
properties: { _label },
} = element
const elementLabel = _label as LabelConfig[]
const idx = findIndex(elementLabel, (cur) => cur.id === label.id)

const target = elementLabel[idx]
elementLabel[idx] = {
...target,
...data,
}

const targetElem = graphModel.getElement(element.id)
targetElem?.setProperty('_label', elementLabel)
}

// 重新计算 Label 大小
reCalcLabelSize = () => {}

Expand All @@ -175,37 +210,49 @@ export class Label extends Component<ILabelProps, ILabelState> {
const { label, element, graphModel } = this.props

// 在点击元素、边或者画布 时,结束 Label 的编辑态
graphModel.eventCenter.on('blank:click,node:click,edge:click', () => {
// 如果当前 label 处于编辑态,则结束编辑态
if (this.state.isEditing) {
this.setState({ isEditing: false })

const value = this.textRef.current?.innerText ?? ''
const content = this.textRef.current?.innerHTML ?? ''

const {
properties: { _label },
} = element
const elementLabel = _label as LabelConfig[]
const idx = findIndex(elementLabel, (cur) => cur.id === label.id)

const target = elementLabel[idx]
elementLabel[idx] = {
...target,
value,
content,
graphModel.eventCenter.on(
'blank:click,node:click,edge:click,label:click',
({ data }) => {
// 点击的不是label 、点击的不是当前label、点击的是当前label,且当前 label 处于选中态
// 则取消选中态
if (
data?.type !== 'label' ||
(data.type === 'label' && data.id !== label.id) ||
this.state.isSelected
) {
this.setState({ isSelected: false })
}

const targetElem = graphModel.getElement(element.id)
targetElem?.setProperty('_label', elementLabel)

element.setElementState(ElementState.DEFAULT)
}
if (this.textRef.current) {
this.textRef.current.contentEditable = 'false'
}
})

// 点击的不是label 、点击的不是当前label、点击的是当前label,且当前 label 处于编辑态
// 则结束编辑态
if (
(data?.type !== 'label' ||
(data.type == 'label' && data.id !== label.id)) &&
this.state.isEditing
) {
this.setState({ isEditing: false })

const value = this.textRef.current?.innerText ?? ''
const content = this.textRef.current?.innerHTML ?? ''

this.setElementModelLabelInfo({
value,
content,
isSelected: false,
})

element.setElementState(ElementState.DEFAULT)
}
// 点击的不是label 、点击的不是当前label、点击的是当前label,且当前 label 的文本DOM存在
// 则结束文本DOM的编辑态
if (
(data?.type !== 'label' ||
(data.type == 'label' && data.id !== label.id)) &&
this.textRef.current
) {
this.textRef.current.contentEditable = 'false'
}
},
)
// TODO: 节点拖拽结束后,更新 Label 的位置
// eventCenter.on('node:drag', () => {})
// eventCenter.on('node:drop', () => {})
Expand All @@ -216,7 +263,7 @@ export class Label extends Component<ILabelProps, ILabelState> {

componentDidUpdate() {
// snapshot: any, // previousState: Readonly<ILabelState>, // previousProps: Readonly<ILabelProps>,
console.log('Label componentDidUpdate')
// console.log('Label componentDidUpdate')
// console.log('previousProps', previousProps)
// console.log('previousState', previousState)
// console.log('snapshot', snapshot)
Expand All @@ -232,7 +279,7 @@ export class Label extends Component<ILabelProps, ILabelState> {

render() {
const { label, element, graphModel } = this.props
const { isDragging, isHovered, isEditing } = this.state
const { isDragging, isHovered, isSelected, isEditing } = this.state
const { transformModel } = graphModel
const { transform } = transformModel.getTransformStyle()
const {
Expand Down Expand Up @@ -260,13 +307,14 @@ export class Label extends Component<ILabelProps, ILabelState> {
? `${transform} rotate(${rotate}deg)`
: `${transform} rotate(${vertical ? -0.25 : 0}turn)`,
}

return (
<div
id={`element-container-${id}`}
className={classNames('lf-label-editor-container')}
style={containerStyle}
onMouseDown={this.handleMouseDown}
onMouseUp={this.handleMouseUp}
onClick={this.handleClick}
onDblClick={this.handleDbClick}
onBlur={this.handleBlur}
onMouseEnter={this.setHoverOn}
Expand All @@ -279,12 +327,15 @@ export class Label extends Component<ILabelProps, ILabelState> {
className={classNames('lf-label-editor', {
'lf-label-editor-dragging': isDragging,
'lf-label-editor-editing': isEditing,
'lf-label-editor-hover': !isEditing && isHovered,
'lf-label-editor-hover': !isEditing && (isHovered || isSelected),
[`lf-label-editor-${textOverflowMode}`]: !isEditing,
})}
style={{
maxWidth: `${maxLabelWidth}px`,
width: `${maxLabelWidth}px`,
boxSizing: 'border-box',
display: 'inline-block',
background:
isEditing || element.BaseType === 'edge' ? '#fff' : 'transparent',
...style,
}}
dangerouslySetInnerHTML={{ __html: content }}
Expand Down
1 change: 1 addition & 0 deletions packages/extension/src/tools/label/LabelModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export class LabelModel {
id: this.id,
x: this.x,
y: this.y,
type: 'label',
Copy link
Collaborator

Choose a reason for hiding this comment

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

增加了该 type 标识,但 LabelData 类型和 LabelConfig 类型中都没有改属性,所以增加 core 包类型定义,解决打包报错的问题

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

let me cc

content: this.content,
value: this.value,
rotate: this.rotate,
Expand Down
Loading