From 62cd7ba8a743ad87a886ac398350a28b63da06ab Mon Sep 17 00:00:00 2001 From: Dymonelewis <120695700@qq.com> Date: Thu, 12 Dec 2024 11:12:37 +0800 Subject: [PATCH 1/5] =?UTF-8?q?fix(core/polyline):=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E6=B5=81=E7=A8=8B=E5=9B=BE=E5=88=9D=E6=AC=A1=E6=B8=B2=E6=9F=93?= =?UTF-8?q?=E6=97=B6=E5=8D=B3=E4=BD=BF=E4=BC=A0=E5=85=A5pointsList?= =?UTF-8?q?=E6=8A=98=E7=BA=BF=E8=B7=AF=E5=BE=84=E4=B9=9F=E4=BC=9A=E9=87=8D?= =?UTF-8?q?=E7=BD=AE=E9=97=AE=E9=A2=98&=E6=96=B0=E5=A2=9E=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E6=8A=98=E7=BA=BFpointsList=E7=9A=84=E6=96=B9?= =?UTF-8?q?=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/core/src/model/edge/PolylineEdgeModel.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/core/src/model/edge/PolylineEdgeModel.ts b/packages/core/src/model/edge/PolylineEdgeModel.ts index d55b5c085..6dcacaaec 100644 --- a/packages/core/src/model/edge/PolylineEdgeModel.ts +++ b/packages/core/src/model/edge/PolylineEdgeModel.ts @@ -35,6 +35,9 @@ export class PolylineEdgeModel extends BaseEdgeModel { initEdgeData(data: LogicFlow.EdgeConfig): void { this.offset = 30 + if (data.pointsList) { + this.pointsList = data.pointsList + } super.initEdgeData(data) } @@ -315,6 +318,11 @@ export class PolylineEdgeModel extends BaseEdgeModel { return list } + updatePath(pointList: Point[]) { + this.pointsList = pointList + this.points = this.getPath(this.pointsList) + } + getData() { const data = super.getData() const pointsList = this.pointsList.map(({ x, y }) => ({ From 346abd2e1a780bc83f8775df12fa103cc5a8a5ad Mon Sep 17 00:00:00 2001 From: Dymonelewis <120695700@qq.com> Date: Thu, 12 Dec 2024 11:53:23 +0800 Subject: [PATCH 2/5] =?UTF-8?q?fix(core):=20=E7=BD=91=E6=A0=BC=E5=AF=B9?= =?UTF-8?q?=E9=BD=90=E6=94=B9=E4=B8=BA=E5=BC=80=E5=85=B3=E6=8E=A7=E5=88=B6?= =?UTF-8?q?=20&=20=E4=BF=AE=E5=A4=8D=E5=88=9D=E5=A7=8B=E5=8C=96=E6=97=B6?= =?UTF-8?q?=E6=B5=81=E7=A8=8B=E5=9B=BE=E5=81=8F=E7=A7=BB=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/core/src/LogicFlow.tsx | 18 ++++- packages/core/src/model/EditConfigModel.ts | 4 ++ packages/core/src/model/GraphModel.ts | 71 ++++--------------- packages/core/src/util/geometry.ts | 4 +- packages/core/src/view/behavior/dnd.ts | 7 +- packages/core/src/view/node/BaseNode.tsx | 8 +-- .../core/src/view/overlay/CanvasOverlay.tsx | 11 +-- 7 files changed, 52 insertions(+), 71 deletions(-) diff --git a/packages/core/src/LogicFlow.tsx b/packages/core/src/LogicFlow.tsx index 706a0d7b2..6336a7c14 100644 --- a/packages/core/src/LogicFlow.tsx +++ b/packages/core/src/LogicFlow.tsx @@ -1,5 +1,5 @@ import { ComponentType, createElement as h, render } from 'preact/compat' -import { cloneDeep, forEach, indexOf } from 'lodash-es' +import { cloneDeep, forEach, indexOf, isNil } from 'lodash-es' import { observer } from '.' import { Options as LFOptions } from './options' import * as _Model from './model' @@ -885,12 +885,28 @@ export class LogicFlow { */ updateEditConfig(config: Partial) { const { editConfigModel, transformModel } = this.graphModel + const currentSnapGrid = editConfigModel.snapGrid + editConfigModel.updateEditConfig(config) if (config?.stopMoveGraph !== undefined) { transformModel.updateTranslateLimits(config.stopMoveGraph) } + // 静默模式切换时,修改快捷键的启用状态 config?.isSilentMode ? this.keyboard.disable() : this.keyboard.enable(true) + + // 切换网格对齐状态时,修改网格尺寸 + if (!isNil(config?.snapGrid) && config.snapGrid !== currentSnapGrid) { + const { + grid: { size = 1 }, + editConfigModel: { snapGrid }, + gridSize, + } = this.graphModel + // 开启网格对齐且当前画布网格尺寸与网格对齐尺寸不一致时,或者关闭网格对齐且当前画布网格尺寸不为1时,更新画布网格尺寸 + if ((snapGrid && gridSize !== size) || (!snapGrid && gridSize !== 1)) { + this.graphModel.updateGridSize(snapGrid ? size : 1) + } + } } /** diff --git a/packages/core/src/model/EditConfigModel.ts b/packages/core/src/model/EditConfigModel.ts index 5e51ee28b..88ae0b37e 100644 --- a/packages/core/src/model/EditConfigModel.ts +++ b/packages/core/src/model/EditConfigModel.ts @@ -123,6 +123,8 @@ export interface IEditConfigType { nodeTextMode: TextMode // 边文本类型 edgeTextMode: TextMode + // 开启网格对齐 + snapGrid: boolean } export type IConfigKeys = keyof IEditConfigType @@ -154,6 +156,7 @@ const allKeys = [ 'stopZoomGraph', // 禁止缩放画布 'stopScrollGraph', // 禁止鼠标滚动移动画布 'stopMoveGraph', // 禁止拖动画布 + 'snapGrid', // 是否开启网格对齐 'adjustEdge', // 允许调整边 'adjustEdgeMiddle', // 允许调整边中点 'adjustEdgeStartAndEnd', // 允许调整边起点和终点 @@ -198,6 +201,7 @@ export class EditConfigModel { @observable stopZoomGraph = false @observable stopMoveGraph = false @observable stopScrollGraph = false + @observable snapGrid = false /********************************************************* * 文本相关配置(全局) ********************************************************/ diff --git a/packages/core/src/model/GraphModel.ts b/packages/core/src/model/GraphModel.ts index ef229c95a..03feffe26 100644 --- a/packages/core/src/model/GraphModel.ts +++ b/packages/core/src/model/GraphModel.ts @@ -5,7 +5,6 @@ import { merge, isBoolean, debounce, - isEqual, isNil, } from 'lodash-es' import { action, computed, observable } from 'mobx' @@ -50,7 +49,6 @@ import Position = LogicFlow.Position import PointTuple = LogicFlow.PointTuple import GraphData = LogicFlow.GraphData import NodeConfig = LogicFlow.NodeConfig -import AnchorConfig = Model.AnchorConfig import BaseNodeModelCtor = LogicFlow.BaseNodeModelCtor import BaseEdgeModelCtor = LogicFlow.BaseEdgeModelCtor @@ -162,7 +160,8 @@ export class GraphModel { this.rootEl = container this.partial = !!partial this.background = background - if (typeof grid === 'object') { + if (typeof grid === 'object' && options.snapGrid) { + // 开启网格对齐时才根据网格尺寸设置步长 this.gridSize = grid.size || 1 // 默认 gridSize 设置为 1 } this.theme = setupTheme(options.style) @@ -490,58 +489,6 @@ export class GraphModel { throw new Error(`找不到${edge.type}对应的边。`) } const edgeModel = new Model(edge, this) - // 根据edgeModel中存储的数据找到当前画布上的起终锚点坐标 - // 判断当前起终锚点数据和Model中存储的起终点数据是否一致,不一致更新起终点信息 - const { - sourceNodeId, - targetNodeId, - sourceAnchorId = '', - targetAnchorId = '', - startPoint, - endPoint, - text, - textPosition, - } = edgeModel - const updateAnchorPoint = ( - node: BaseNodeModel | undefined, - anchorId: string, - point: Position, - updatePoint: (anchor: AnchorConfig) => void, - ) => { - const anchor = node?.anchors.find((anchor) => anchor.id === anchorId) - if (anchor && !isEqual(anchor, point)) { - updatePoint(anchor) - } - } - - const sourceNode = this.getNodeModelById(sourceNodeId) - const targetNode = this.getNodeModelById(targetNodeId) - - updateAnchorPoint( - sourceNode, - sourceAnchorId, - startPoint, - edgeModel.updateStartPoint.bind(edgeModel), - ) - updateAnchorPoint( - targetNode, - targetAnchorId, - endPoint, - edgeModel.updateEndPoint.bind(edgeModel), - ) - - // 而文本需要先算一下文本与默认文本位置之间的相对位置差 - // 再计算新路径的文本默认位置,加上相对位置差,得到调整后边的文本的位置 - if (text) { - const { x, y } = text - const { x: defaultX, y: defaultY } = textPosition - if (x && y && defaultX && defaultY) { - const deltaX = x - defaultX - const deltaY = y - defaultY - edgeModel.resetTextPosition() - edgeModel.moveText(deltaX, deltaY) - } - } this.edgeModelMap.set(edgeModel.id, edgeModel) this.elementsModelMap.set(edgeModel.id, edgeModel) @@ -900,6 +847,7 @@ export class GraphModel { */ getModelAfterSnapToGrid(node: NodeConfig) { const Model = this.getModel(node.type) as BaseNodeModelCtor + const { snapGrid } = this.editConfigModel if (!Model) { throw new Error( `找不到${node.type}对应的节点,请确认是否已注册此类型节点。`, @@ -908,8 +856,8 @@ export class GraphModel { const { x: nodeX, y: nodeY } = node // 根据 grid 修正节点的 x, y if (nodeX && nodeY) { - node.x = snapToGrid(nodeX, this.gridSize) - node.y = snapToGrid(nodeY, this.gridSize) + node.x = snapToGrid(nodeX, this.gridSize, snapGrid) + node.y = snapToGrid(nodeY, this.gridSize, snapGrid) if (typeof node.text === 'object' && node.text !== null) { // 原来的处理是:node.text.x -= getGridOffset(nodeX, this.gridSize) // 由于snapToGrid()使用了Math.round()四舍五入的做法,因此无法判断需要执行 @@ -1526,7 +1474,14 @@ export class GraphModel { } /** - * 更新网格配置 + * 更新网格尺寸 + */ + updateGridSize(size: number) { + this.gridSize = size + } + + /** + * 更新背景配置 */ updateBackgroundOptions( options: boolean | Partial, diff --git a/packages/core/src/util/geometry.ts b/packages/core/src/util/geometry.ts index 313fddb62..e9f7321af 100644 --- a/packages/core/src/util/geometry.ts +++ b/packages/core/src/util/geometry.ts @@ -1,7 +1,9 @@ import LogicFlow from '../LogicFlow' import PointTuple = LogicFlow.PointTuple -export function snapToGrid(point: number, gridSize: number) { +export function snapToGrid(point: number, gridSize: number, snapGrid: boolean) { + // 开启节网格对齐时才根据网格尺寸校准坐标 + if (!snapGrid) return point // 保证 x, y 的值为 gridSize 的整数倍 return gridSize * Math.round(point / gridSize) || point } diff --git a/packages/core/src/view/behavior/dnd.ts b/packages/core/src/view/behavior/dnd.ts index 737b077d6..ea3cc2341 100644 --- a/packages/core/src/view/behavior/dnd.ts +++ b/packages/core/src/view/behavior/dnd.ts @@ -26,10 +26,13 @@ export class Dnd { }) // 处理缩放和偏移 const { x: x1, y: y1 } = position.canvasOverlayPosition + const { + editConfigModel: { snapGrid }, + } = this.lf.graphModel // x, y 对齐到网格的 size return { - x: snapToGrid(x1, gridSize), - y: snapToGrid(y1, gridSize), + x: snapToGrid(x1, gridSize, snapGrid), + y: snapToGrid(y1, gridSize, snapGrid), } } diff --git a/packages/core/src/view/node/BaseNode.tsx b/packages/core/src/view/node/BaseNode.tsx index d4bb29a88..c02190db3 100644 --- a/packages/core/src/view/node/BaseNode.tsx +++ b/packages/core/src/view/node/BaseNode.tsx @@ -241,7 +241,7 @@ export abstract class BaseNode

extends Component< onDragging = ({ event }: IDragParams) => { const { model, graphModel } = this.props const { - editConfigModel: { stopMoveGraph, autoExpand }, + editConfigModel: { stopMoveGraph, autoExpand, snapGrid }, transformModel, selectNodes, width, @@ -261,9 +261,9 @@ export abstract class BaseNode

extends Component< // 2. 考虑鼠标位置不再节点中心 x = x + (this.moveOffset?.dx ?? 0) y = y + (this.moveOffset?.dy ?? 0) - // 将x, y移动到grid上 - x = snapToGrid(x, gridSize) - y = snapToGrid(y, gridSize) + // 校准坐标 + x = snapToGrid(x, gridSize, snapGrid) + y = snapToGrid(y, gridSize, snapGrid) if (!width || !height) { graphModel.moveNode2Coordinate(model.id, x, y) return diff --git a/packages/core/src/view/overlay/CanvasOverlay.tsx b/packages/core/src/view/overlay/CanvasOverlay.tsx index f2cf520a1..a245ada28 100644 --- a/packages/core/src/view/overlay/CanvasOverlay.tsx +++ b/packages/core/src/view/overlay/CanvasOverlay.tsx @@ -65,8 +65,9 @@ export class CanvasOverlay extends Component { graphModel, } = this.props const { deltaX: eX, deltaY: eY } = ev + const { stopScrollGraph, stopZoomGraph } = editConfigModel // 如果没有禁止滚动移动画布, 并且当前触发的时候ctrl键、cmd键没有按住, 那么移动画布 - if (!editConfigModel.stopScrollGraph && !ev.ctrlKey && !ev.metaKey) { + if (!stopScrollGraph && !ev.ctrlKey && !ev.metaKey) { ev.preventDefault() this.stepScrollX += eX this.stepScrollY += eY @@ -85,7 +86,7 @@ export class CanvasOverlay extends Component { return } // 如果没有禁止缩放画布,那么进行缩放. 在禁止缩放画布后,按住 ctrl、cmd 键也不能缩放了。 - if (!editConfigModel.stopZoomGraph) { + if (!stopZoomGraph) { ev.preventDefault() const position = graphModel.getPointByClient({ x: ev.clientX, @@ -133,11 +134,11 @@ export class CanvasOverlay extends Component { gridSize, }, } = this.props + const { adjustEdge, adjustNodePosition, stopMoveGraph } = editConfigModel const target = ev.target as HTMLElement - const isFrozenElement = - !editConfigModel.adjustEdge && !editConfigModel.adjustNodePosition + const isFrozenElement = !adjustEdge && !adjustNodePosition if (target.getAttribute('name') === 'canvas-overlay' || isFrozenElement) { - if (editConfigModel.stopMoveGraph !== true) { + if (stopMoveGraph !== true) { this.stepDrag.setStep(gridSize * SCALE_X) this.stepDrag.handleMouseDown(ev) } else { From dd001c737e2ace587d8936852511a123d1d13c21 Mon Sep 17 00:00:00 2001 From: Dymonelewis <120695700@qq.com> Date: Thu, 12 Dec 2024 11:53:57 +0800 Subject: [PATCH 3/5] =?UTF-8?q?feat(examples):=20=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E7=BD=91=E6=A0=BC=E5=AF=B9=E9=BD=90demo=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/pages/edges/custom/polyline/index.tsx | 19 ++++++++++++- .../src/pages/graph/index.tsx | 27 +++++++++++++------ 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/examples/feature-examples/src/pages/edges/custom/polyline/index.tsx b/examples/feature-examples/src/pages/edges/custom/polyline/index.tsx index e960f00f3..a891e7fd2 100644 --- a/examples/feature-examples/src/pages/edges/custom/polyline/index.tsx +++ b/examples/feature-examples/src/pages/edges/custom/polyline/index.tsx @@ -21,7 +21,7 @@ export default function CustomPolylineEdge() { ...config, container: containerRef.current as HTMLElement, grid: { - size: 10, + size: 20, }, }) @@ -307,6 +307,23 @@ export default function CustomPolylineEdge() { > 开关动画 +