didi / didi/LogicFlow

[Bug Report]: 自定义锚点时的非正常情况

Open
#2,365 2 comments 0 reactions 1 assignee Claimed by @CraneReturn View on GitHub
core: anchor priority:P2 status: todo type:feature-require
Dominant language
TypeScript
Stars
11.7k
Forks
1.4k
PR merge metrics
No merged PRs in 30d

Description

### 发生了什么?

### 背景
在使用HtmlNodeModel、HtmlNode自定义节点时,由于自定义节点中的锚点需要通过渲染后才可以计算出位置,在本例中使用修改anchorsOffset属性来达到目的,重写了getDefaultAnchors方法返回出锚点的基本信息和自定义信息,然后setAttributes中自定义properties的anchorsOffset属性,最后赋值到model中的anchorsOffset。
### 问题
但是页面中的锚点位置确实更新了,只是在重写getConnectedTargetRules方法时返回每个规则的validate中的targetAnchor或sourceAnchor参数信息不包含自定义的属性,例如本例中的type: "in",在修改anchorsOffset前后通过打印日志
`console.log(this.props.model.anchors)`
发现anchors中的数据已变成baseModel中实现方法getDefaultAnchor,也就是默认的锚点信息,下图中左侧正常锚点是未修改自定义节点的anchorsOffset的数据,右侧为修改过后的

Image

### 核心代码
```
class BaseFlowNodeView extends HtmlNode {

setHtml(rootEl) {

const model = this.props.model
const { id, containerClassName, mainColor, secondaryColor, icon, height } = model

// 根部容器
const container = document.createElement("div")
container.className = `node-container ${containerClassName}`
container.style = `border: 1.5px solid ${mainColor}`
container.id = id

// 头部
const header = document.createElement("div")
header.className = 'header'
header.style = `
background-color: ${secondaryColor};
border-bottom: 1px solid ${secondaryColor};
`
const headerIcon = document.createElement('i')
headerIcon.style = `color: ${mainColor}`
headerIcon.className = 'icon'
headerIcon.innerHTML = icon
header.appendChild(headerIcon)

const headerTitle = document.createElement("div")
headerTitle.className = 'title';
headerTitle.style = `color: ${mainColor}`;
headerTitle.innerText = model.getProperties().title || ''
header.appendChild(headerTitle)

container.appendChild(header)

// 主内容区域
const body = document.createElement("div")
body.className = 'body'

const main = this.getMain()
if (main) {
body.appendChild(main)
}
container.appendChild(body)

rootEl.innerHTML = ''
rootEl.appendChild(container)

const updateProperties = this.getUpdateProperties();

const newHeight = document.getElementById(id).getBoundingClientRect().height
if (height != newHeight) {
updateProperties.height = newHeight
}
model.setProperties(updateProperties)
}

getUpdateProperties() {
return {}
}

getRelativePosition(element, container) {
const elemRect = element.getBoundingClientRect();
const containerRect = container.getBoundingClientRect();

const relativeX = elemRect.left - containerRect.left;
const relativeY = elemRect.top - containerRect.top;

return { x: relativeX, y: relativeY };
}

}

class BaseFlowNodeModel extends HtmlNodeModel {

setAttributes() {
this.text.editable = false;
this.isRestrict = true
this.autoResize = true
this.collapsible = false
const { height = 200 } = this.properties
this.height = height

// 自定义通用属性
this.containerClassName = ''
this.mainColor = '#332d2d'
this.secondaryColor = '#eee'
this.icon =
`
`
this.setExtraAttributes();
}

getConnectedTargetRules() {
const rules = super.getConnectedTargetRules();
rules.push({
message: '不允许连接此锚点',
validate(sourceNode, targetNode, sourceAnchor, targetAnchor) {
console.log(sourceNode, targetNode, sourceAnchor, targetAnchor);
return true;
}
});
return rules;
}
}

export {
BaseFlowNodeView,
BaseFlowNodeModel
}

import { BaseFlowNodeModel, BaseFlowNodeView } from "./BaseFLowNode"
import '@/assets/logic_flow/node/action_node.css'
import { toJS } from 'mobx';

class ActionNodeView extends BaseFlowNodeView {

getMain() {
const model = this.props.model
const { id } = model
const properties = model.getProperties()
const actions = properties.actions || []

const actionContainer = document.createElement("div")
actions.forEach(action => {
const span = document.createElement("span")
span.className = 'action'
span.id = `${id}_${action.value}`
span.innerText = action.title
actionContainer.appendChild(span)
})

return actionContainer
}

getUpdateProperties() {
const { height, } = this.props.model
return { anchorsOffset: [[0, - height / 2], [0, height / 2]] }
}
}

class ActionNodeModel extends BaseFlowNodeModel {

setExtraAttributes() {
const { height = 150 } = this.properties;
this.text.editable = false;
this.isRestrict = true
this.autoResize = true
this.collapsible = false

this.width = 250;
this.height = height;

this.radius = 5;

this.containerClassName = 'action-container'
this.mainColor = '#2080f0'
this.secondaryColor = 'rgba(32, 128, 240, 0.16)'
this.icon =
`

`

const { anchorsOffset = [] } = this.properties
this.anchorsOffset = toJS(anchorsOffset)
}

getDefaultAnchor() {
const { x, y, id } = this
return [{ x, y, id: `${id}_in`, type: 'in' }, { x, y, id: `${id}_out`, type: 'out' }]
}
}

export default {
type: "action",
view: ActionNodeView,
model: ActionNodeModel
}
```

### logicflow/core版本

2.1.1

### logicflow/extension版本

2.1.1

### logicflow/engine版本

_No response_

### 浏览器&环境

Chrome

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.