-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Open
Labels
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的数据,右侧为修改过后的
核心代码
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 =
`<svg width="23" height="23" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24">
<g fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M12 3l8 4.5v9L12 21l-8-4.5v-9L12 3"></path><path d="M12 12l8-4.5"></path>
<path d="M12 12v9"></path>
<path d="M12 12L4 7.5"></path>
</g>
</svg>
`
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 =
`
<svg width="20" height="20" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24">
<g fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M4 21V8a3 3 0 0 1 3-3h10a3 3 0 0 1 3 3v6a3 3 0 0 1-3 3H8l-4 4"></path><path d="M8 9h8"></path>
<path d="M8 13h6"></path>
</g>
</svg>
`
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