UNPKG

@logicflow/core

Version:

LogicFlow, help you quickly create flowcharts

198 lines (190 loc) 5.13 kB
import { get, assign, cloneDeep } from 'lodash-es' import { action, observable } from 'mobx' import BaseEdgeModel from './BaseEdgeModel' import { BaseNodeModel } from '../node' import LogicFlow from '../../LogicFlow' import GraphModel from '../GraphModel' import { ModelType } from '../../constant' import { getBezierControlPoints, IBezierControls } from '../../util' import Point = LogicFlow.Point import EdgeConfig = LogicFlow.EdgeConfig export class BezierEdgeModel extends BaseEdgeModel { modelType = ModelType.BEZIER_EDGE @observable offset!: number @observable path = '' constructor(data: EdgeConfig, graphModel: GraphModel) { super(data, graphModel) this.initEdgeData(data) this.setAttributes() } initEdgeData(data: EdgeConfig): void { this.offset = get(data, 'properties.offset', 100) super.initEdgeData(data) } getEdgeStyle() { const { bezier } = this.graphModel.theme const style = super.getEdgeStyle() const { style: customStyle = {} } = this.properties return { ...style, ...cloneDeep(bezier), ...cloneDeep(customStyle), } } getTextPosition(): Point { if (this.pointsList && this.pointsList.length > 0) { let pointsXSum = 0 let pointsYSum = 0 this.pointsList.forEach(({ x, y }) => { pointsXSum += x pointsYSum += y }) return { x: pointsXSum / this.pointsList.length, y: pointsYSum / this.pointsList.length, } } return { x: (this.startPoint.x + this.endPoint.x) / 2, y: (this.startPoint.y + this.endPoint.y) / 2, } } getData() { const data = super.getData() const pointsList = this.pointsList.map(({ x, y }) => ({ x, y })) return { ...data, pointsList, } } /* 获取贝塞尔曲线的控制点 */ private getControls(): IBezierControls { const start = this.startPoint const end = this.endPoint const points = getBezierControlPoints({ start, end, sourceNode: this.sourceNode, targetNode: this.targetNode, offset: this.offset, }) return points } /* 获取贝塞尔曲线的path */ private getPath(points: Point[]): string { const [start, sNext, ePre, end] = points return `M ${start.x} ${start.y} C ${sNext.x} ${sNext.y}, ${ePre.x} ${ePre.y}, ${end.x} ${end.y}` } @action initPoints() { if (this.pointsList.length > 0) { this.path = this.getPath(this.pointsList) } else { this.updatePoints() } } @action updatePoints() { const { sNext, ePre } = this.getControls() this.updatePath(sNext, ePre) } updatePath(sNext: Point, ePre: Point) { sNext = cloneDeep(sNext) ePre = cloneDeep(ePre) const start = { x: this.startPoint.x, y: this.startPoint.y, } const end = { x: this.endPoint.x, y: this.endPoint.y, } if (!sNext || !ePre) { const control = this.getControls() sNext = control.sNext ePre = control.ePre } this.pointsList = [start, sNext, ePre, end] this.path = this.getPath(this.pointsList) } @action updateStartPoint(anchor: Point) { this.startPoint = Object.assign({}, anchor) this.updatePoints() } @action updateEndPoint(anchor: Point) { this.endPoint = Object.assign({}, anchor) this.updatePoints() } @action moveStartPoint(deltaX: number, deltaY: number): void { this.startPoint.x += deltaX this.startPoint.y += deltaY const [, sNext, ePre] = this.pointsList // 保持调整点一起移动 sNext.x += deltaX sNext.y += deltaY this.updatePath(sNext, ePre) } @action moveEndPoint(deltaX: number, deltaY: number): void { this.endPoint.x += deltaX this.endPoint.y += deltaY const [, sNext, ePre] = this.pointsList // 保持调整点一起移动 ePre.x += deltaX ePre.y += deltaY this.updatePath(sNext, ePre) } @action updateAdjustAnchor(anchor: Point, type: string) { if (type === 'sNext') { this.pointsList[1] = anchor } else if (type === 'ePre') { this.pointsList[2] = anchor } this.path = this.getPath(this.pointsList) if (this.text?.value) { this.setText(assign({}, this.text, this.textPosition)) } } // 获取边调整的起点 @action getAdjustStart() { return this.pointsList[0] || this.startPoint } // 获取边调整的终点 @action getAdjustEnd() { const { pointsList } = this return pointsList[pointsList.length - 1] || this.endPoint } // 起终点拖拽调整过程中,进行曲线路径更新 @action updateAfterAdjustStartAndEnd({ startPoint, endPoint, sourceNode, targetNode, }: { startPoint: Point endPoint: Point sourceNode: BaseNodeModel targetNode: BaseNodeModel }) { const { sNext, ePre } = getBezierControlPoints({ start: startPoint, end: endPoint, sourceNode, targetNode, offset: this.offset, }) this.pointsList = [startPoint, sNext, ePre, endPoint] this.initPoints() } } export default BezierEdgeModel