拓冰建站拓冰建站
首页 / 资讯中心 / 正文

LogicFlow 画布 API 完全指南:resize / focusOn / zoom / fitView 与坐标换算实战

LogicFlow 画布 API 完全指南resize / focusOn / zoom / fitView 与坐标换算实战【免费下载链接】LogicFlowA flow chart editing framework focus on business customization. 专注于业务自定义的流程图编辑框架支持实现脑图、ER图、UML、工作流等各种图编辑场景。项目地址: https://gitcode.com/GitHub_Trending/lo/LogicFlow本文以 LogicFlow 实例的画布相关 API 文档为主体系统讲解画布尺寸调整、视口变换缩放与平移、坐标体系换算、元素层级与边动画共 16 个实例方法。结合packages/core中LogicFlow.tsx、TransformModel.ts、GraphModel.ts与BaseEdgeModel.ts的源码实现帮助读者掌握每个方法的签名、行为细节、底层原理并给出可直接落地的组合使用方案。LogicFlow 是一个专注于业务自定义的流程图编辑框架。在实际业务中无论是工具栏上的放大缩小按钮、导航栏里的回到中心/自适应画布还是右键菜单里的置顶元素背后都由一组画布级实例方法驱动。本文要解决的正是这一层能力如何精确控制画布尺寸、如何缩放与平移视口、如何在页面坐标与画布坐标之间换算、如何管理元素层级与边动画。读完本文你将能熟练使用resize、focusOn、zoom、fitView、getPointByClient等 API并理解它们各自在底层如何影响TransformModel的变换矩阵。一、方法总览与调用入口所有画布相关方法都定义在 LogicFlow 实例lf上核心实现集中在 packages/core/src/LogicFlow.tsx 的 Graph 相关方法 区块约 L939-L1295。它们大多是一层薄封装真正的状态与计算逻辑位于GraphModel与TransformModel中方法作用底层委托对象resize(width?, height?)调整画布尺寸GraphModel.resizefocusOn(focusOnArgs)视口中心定位到节点/坐标TransformModel.focusOnzoom(zoomSize?, point?)按步进或倍率缩放TransformModel.zoomresetZoom()缩放重置为 1TransformModel.resetZoomsetZoomMiniSize(size)设置最小缩放倍数TransformModelsetZoomMaxSize(size)设置最大缩放倍数TransformModelgetTransform()获取缩放/平移状态TransformModel各 observable 字段translate(x, y)相对偏移平移画布TransformModel.translateresetTranslate()平移复位基于translate反向补偿translateCenter()图形内容居中显示GraphModel.translateCenterfitView(v?, h?)图形自适应视口GraphModel.fitViewgetPointByClient(x, y)页面坐标转画布坐标GraphModel.getPointByClienttoFront(id)元素置顶GraphModel.toFrontopenEdgeAnimation(edgeId)开启边动画BaseEdgeModel.openEdgeAnimationcloseEdgeAnimation(edgeId)关闭边动画BaseEdgeModel.closeEdgeAnimation理解这张表之后下文按尺寸、视口定位、缩放、平移、自适应、坐标换算、层级、边动画八个主题逐一深入。二、画布尺寸resize签名resize(width?: number, height?: number): voidresize用于调整画布尺寸不传参数时自动按容器container当前的实际尺寸重算。源码中LogicFlow.resize将调用透传给graphModel.resize(width, height)并同步回写this.options.width / this.options.height见 LogicFlow.tsx#L1024-L1028。从 GraphModel.ts#L1609-L1637 可以看到底层实现有三层保护性检查这对实际调用非常有指导意义实例未销毁rootEl不存在时直接返回元素仍在 DOM 中通过document.body.contains(this.rootEl)判断容器是否已被移除元素可见通过this.rootEl.offsetParent ! null判断容器是否可见例如处于display: none状态。通过检查后宽高取值逻辑为this.width width ?? this.rootEl.getBoundingClientRect().width this.height height ?? this.rootEl.getBoundingClientRect().height即显式传入的宽高优先否则读取getBoundingClientRect()的结果。若容器可见但计算出的宽高为 0控制台会输出警告提示确认 container 已挂载到 DOM。另外值得注意GraphModel内部使用ResizeObserver监听容器尺寸变化并自动调用resize()见 GraphModel.ts#L207-L228同时会发出graph:resize事件。因此绝大多数场景下你无需手动调用resize只有容器尺寸发生非常规变化例如动画过渡、拖拽改变面板宽度后时才需要显式触发。三、视口中心定位focusOn签名focusOn(focusOnArgs: { id?: string; coordinate?: { x: number; y: number } }): voidfocusOn将视口中心移动到指定元素或坐标点。它实际上是重载方法从 LogicFlow.tsx#L998-L1018 可以看到支持三种入参形态传入string视为元素 id通过focusByElement找到节点中心nodeModel.getData()的 x/y或边的文本位置edgeModel.textPosition传入{ x, y }视为画布坐标直接执行focusByCoordinate传入{ id?, coordinate? }标准文档形态两者二选一。底层计算在 TransformModel.ts#L227-L234 的focusOn中完成核心思路是先求差、再平移const [x, y] this.CanvasPointToHtmlPoint([targetX, targetY]) const [deltaX, deltaY] [width / 2 - x, height / 2 - y] this.TRANSLATE_X deltaX this.TRANSLATE_Y deltaY即先把目标画布坐标通过CanvasPointToHtmlPoint乘缩放比例并加平移量见 TransformModel.ts#L96-L102换算成当前视口下的 HTML 坐标再计算视口中心点与该点的差值最后把差值叠加到平移量上从而让目标点恰好落在视口中央。一个常见误区focusOn只改变平移TRANSLATE不会改变缩放SCALE。若想让目标点以特定倍率居中显示需要先zoom再focusOn下文常见组合示例会给出完整写法。四、缩放控制zoom / resetZoom / setZoomMiniSize / setZoomMaxSize4.1 zoom按步进或倍率缩放签名zoom(zoomSize?: boolean | number, point?: [number, number]): stringzoomSize为boolean时按内置步进缩放true放大、false缩小步长为ZOOM_SIZE 0.04即每次变化 4%见 TransformModel.ts#L57 与 TransformModel.ts#L152-L180zoomSize为number时直接设置目标倍率小于 1 缩小、大于 1 放大、等于 1 不变point为缩放原点相对画布左上角的坐标传入后缩放会围绕该点进行——实现上是同步修正平移量TRANSLATE_X - (newScaleX - SCALE_X) * point[0]保证原点处的图形位置不因缩放而漂移返回值string类型的当前缩放比例百分比例如100%、120%。缩放会受上下限约束newScaleX小于MINI_SCALE_SIZE默认 0.2或大于MAX_SCALE_SIZE默认 16时直接返回当前比例且不生效。4.2 resetZoom缩放复位resetZoom(): void将SCALE_X、SCALE_Y重置为1见 TransformModel.ts#L196-L201。注意它只重置缩放不影响平移量。4.3 缩放边界setZoomMiniSize / setZoomMaxSizesetZoomMiniSize(size: number): void setZoomMaxSize(size: number): void分别设置缩放允许的最小、最大倍率。默认值定义在 TransformModel.ts#L49-L50MINI_SCALE_SIZE 0.2最小缩到 20%、MAX_SCALE_SIZE 16最大放大到 1600%。典型用法当业务流程不允许用户把图画得过小时可在初始化后收紧最小倍率lf.setZoomMiniSize(0.5) // 最小缩到 50% lf.setZoomMaxSize(2) // 最大放到 200%4.4 变换事件监听zoom、resetZoom、translate、focusOn每次执行后都会通过emitGraphTransform发出GRAPH_TRANSFORMgraph:transform事件携带type与完整的SCALE_X / SCALE_Y / SKEW_X / SKEW_Y / TRANSLATE_X / TRANSLATE_Y六元组见 TransformModel.ts#L182-L194。这为监听画布缩放/平移实时刷新缩略图或工具栏百分比提供了官方事件通道可配合lf.on(graph:transform, cb)使用。五、平移控制translate / resetTranslate / getTransform5.1 translate相对平移translate(x: number, y: number): void按相对偏移量平移画布。底层 TransformModel.ts#L203-L218 在叠加前会校验平移边界if (this.TRANSLATE_X x this.translateLimitMaxX this.TRANSLATE_X x this.translateLimitMinX) { this.TRANSLATE_X x }平移上下限由updateTranslateLimits决定来自初始化选项stopMoveGraph见 TransformModel.ts#L41-L46false四个方向均可无限平移[-Infinity, 0, Infinity, 0]vertical禁止横向移动仅纵向可移horizontal禁止纵向移动仅横向可移也支持传入[minX, minY, maxX, maxY]四元组自定义限制区域。也就是说translate并非无脑累加而是会被stopMoveGraph配置约束的。该配置可通过lf.updateEditConfig({ stopMoveGraph: vertical })动态修改。5.2 resetTranslate平移复位resetTranslate(): void将画布平移状态重置到初始位置。实现非常直观——读取当前平移量并反向平移见 LogicFlow.tsx#L1252-L1256const { TRANSLATE_X, TRANSLATE_Y } transformModel this.translate(-TRANSLATE_X, -TRANSLATE_Y)5.3 getTransform读取变换状态getTransform(): { SCALE_X: number; SCALE_Y: number; TRANSLATE_X: number; TRANSLATE_Y: number; }返回当前缩放与平移四元组见 LogicFlow.tsx#L1227-L1237。在内部TransformModel还维护SKEW_X / SKEW_Y当前恒为 0以及ZOOM_SIZE并据此生成渲染样式matrix(SCALE_X, SKEW_Y, SKEW_X, SCALE_Y, TRANSLATE_X, TRANSLATE_Y)见 TransformModel.ts#L132-L144。典型场景保存/恢复画布视角或读取当前倍率显示在 UI 上const { SCALE_X } lf.getTransform() toolbar.scaleText ${Math.round(SCALE_X * 100)}%六、自适应与居中translateCenter / fitView6.1 translateCenter内容居中translateCenter(): void将图内容所有节点构成的虚拟矩形居中显示在视口内。GraphModel通过getVirtualRectSize计算所有节点的包围盒——遍历所有节点取x ± width/2 ± strokeWidth、y ± height/2 ± strokeWidth的极值见 GraphModel.ts#L1656-L1678然后调用transformModel.focusOn把虚拟矩形中心平移到容器中心见 GraphModel.ts#L1695-L1714。注意图内容为空无节点时方法直接返回不产生任何效果。6.2 fitView内容自适应视口fitView(verticalOffset?: number, horizontalOffset?: number): void自动调整缩放与平移使全部节点完整显示在当前视口并留出边距。参数含义verticalOffset内容距视口上下的边距默认20horizontalOffset内容距视口左右的边距默认20。源码中有一个向后兼容细节LogicFlow.tsx#L1270-L1275只传一个参数时horizontalOffset会被赋值为verticalOffset即fitView(20)等价于fitView(20, 20)。底层算法在 GraphModel.ts#L1721-L1750可概括为三步计算内容虚拟矩形尺寸与中心getVirtualRectSize分别计算 X/Y 两个方向的缩放比取较大者求倒数作为最终缩放倍率const zoomRatioX (virtualRectWidth horizontalOffset) / containerWidth const zoomRatioY (virtualRectHeight verticalOffset) / containerHeight const zoomRatio 1 / Math.max(zoomRatioX, zoomRatioY)取Math.max意味着以更撑满的那个维度为准从而保证内容在两个方向上都不会溢出视口以视口中心为原点执行transformModel.zoom(zoomRatio, point)再通过transformModel.focusOn把虚拟矩形中心移动到视口中心。fitView与translateCenter的区别在于translateCenter只平移不缩放fitView会同时调整缩放与平移。二者配合即可实现先自适应、再精确微调的工作流。七、坐标换算getPointByClient签名getPointByClient(x: number, y: number): { domOverlayPosition: { x: number; y: number }; canvasOverlayPosition: { x: number; y: number }; }将**页面坐标client 坐标**转换为画布坐标同时返回 DOM 层与 SVG 层的两份结果。它同样支持对象入参getPointByClient({ x, y })见 LogicFlow.tsx#L1050-L1064。底层实现在 GraphModel.ts#L401-L419const bbox this.rootEl.getBoundingClientRect() const domOverlayPosition { x: x1 - bbox.left, y: y1 - bbox.top } const [x, y] this.transformModel.HtmlPointToCanvasPoint([ domOverlayPosition.x, domOverlayPosition.y, ]) const canvasOverlayPosition { x, y }两个返回值的语义非常关键domOverlayPosition页面坐标减去画布容器左上角位置即以画布左上角为原点的坐标未考虑缩放与平移。它对应 DOM 覆盖层如 HTML 自定义节点所在的dom-overlay层的坐标系canvasOverlayPosition在上一步基础上再经过HtmlPointToCanvasPoint(x - TRANSLATE_X) / SCALE_X见 TransformModel.ts#L84-L90去除缩放与平移影响即真正的画布/业务坐标。它对应 SVG 覆盖层canvas-overlay层的坐标系与节点数据中的x / y处于同一坐标系。这是所有鼠标点击 → 画布坐标场景的官方入口。例如在画布任意位置右键添加节点时需要用canvasOverlayPosition作为新节点的x / y否则节点位置在画布缩放/平移后会跑偏。八、元素层级toFront签名toFront(id: string): void将指定节点或边置于更高层级置顶。id可以是节点 id 或边 id底层在GraphModel.toFront中同时从nodesMap与edgesMap查找元素见 GraphModel.ts#L806-L824。具体行为与画布的**堆叠模式overlapMode**强相关这一点在 LogicFlow.tsx#L1030-L1039 的注释中有明确说明静态模式STATICtoFront不做任何处理直接返回递增模式INCREASE将目标元素 zIndex 设置为当前最大 zIndex 1默认模式节点在上 / 边在上先把原置顶元素topElement恢复原有层级setZIndex()再将目标元素设为最大 zIndexELEMENT_MAX_Z_INDEX并记录为新的topElement。这意味着默认模式下连续对两个元素调用toFront前一个置顶元素会自动退位始终保持只有一个元素处于最顶层而递增模式下所有被置顶的元素会按调用顺序层层叠高。九、边动画openEdgeAnimation / closeEdgeAnimationopenEdgeAnimation(edgeId: string): void closeEdgeAnimation(edgeId: string): void按边 id 开启或关闭边的流动动画。两个方法在LogicFlow层直接委托给graphModel.openEdgeAnimation / closeEdgeAnimation见 LogicFlow.tsx#L1281-L1289GraphModel再定位到对应边模型调用见 GraphModel.ts#L1756-L1768。真正改变状态的是 BaseEdgeModel.ts#L686-L694openEdgeAnimation(): void { this.isAnimation true } closeEdgeAnimation(): void { this.isAnimation false }即通过响应式字段isAnimation控制边是否渲染动画。常用场景包括流程执行中高亮正在流转的连线数据同步/消息推送链路的状态可视化配合lf.openEdgeAnimation(edgeId)与延时后lf.closeEdgeAnimation(edgeId)实现脉冲效果。需要说明的是动画的实际呈现如虚线流动、流光描边依赖边视图对isAnimation的渲染支持对于业务自定义边需要自行在视图层消费该状态字段。十、常见组合示例与实战建议文档给出了两组经典组合这里结合源码进一步补充注释与说明// 场景一先自适应再居中再按指定倍率缩放 // resize() 不带参数会按容器实际尺寸重算画布宽高含 DOM 可见性检查 lf.resize(); // translateCenter 将所有节点的虚拟矩形中心平移到视口中心不改变缩放 lf.translateCenter(); // zoom(1.2) 直接设置倍率为 120%围绕视口中心缩放 lf.zoom(1.2); // 场景二点坐标转换后定位到该处 // getPointByClient 把页面坐标转换为画布坐标DOM 层 SVG 层 const point lf.getPointByClient(300, 200); // canvasOverlayPosition 与节点 x/y 同一坐标系可直接用于定位 lf.focusOn({ coordinate: point.canvasOverlayPosition });其他高频实战组合// 初始化完成后立即自适应视口 lf.fitView(30, 30); // 点击节点时聚焦到该节点 lf.focusOn({ id: node_1 }); // 工具栏缩小/放大/复位 lf.zoom(false); // 缩小一档×0.96 左右受最小值约束 lf.zoom(true); // 放大一档×1.04 左右受最大值约束 lf.resetZoom(); // 直接回到 100% // 鼠标右键添加节点用 canvasOverlayPosition 作为节点坐标 const handleCanvasClick (e: MouseEvent) { const { canvasOverlayPosition } lf.getPointByClient(e.clientX, e.clientY) lf.addNode({ type: rect, x: canvasOverlayPosition.x, y: canvasOverlayPosition.y }) } // 流程执行时点亮一条边3 秒后熄灭 lf.openEdgeAnimation(edgeId) setTimeout(() lf.closeEdgeAnimation(edgeId), 3000) // 订阅变换事件实时同步工具栏缩放百分比 lf.on(graph:transform, ({ transform }) { console.log(当前缩放比例, ${transform.SCALE_X * 100}%) })关键注意事项缩放与平移独立focusOn/translateCenter只动平移zoom/resetZoom只动缩放fitView两者都动。需要同时控制时请显式组合调用缩放边界全局生效setZoomMiniSize/setZoomMaxSize会影响包括zoom、fitView在内的一切缩放入口因为fitView内部也是走transformModel.zoom同样会被边界拦截坐标换算选对坐标系涉及画布业务坐标一律取canvasOverlayPosition仅需相对容器的 DOM 位置时取domOverlayPosition空画布保护translateCenter、fitView在无节点时直接返回resize在容器不可见/未挂载时会跳过重算必要时请确认容器已挂载层级行为随 overlapMode 变化默认模式与递增模式OverlapMode.INCREASE下toFront语义不同静态模式OverlapMode.STATIC下置顶无效请结合业务选择合适的堆叠模式。结语画布 API 是 LogicFlow 实例层最常用的能力集合之一。本文从官方文档的 16 个方法出发逐一落到LogicFlow.tsx → GraphModel → TransformModel / BaseEdgeModel的调用链上解释了缩放边界、平移限制、坐标双层的换算原理以及fitView的取最大值算法等源码细节。掌握这些方法及其底层行为足以支撑工具栏、缩略图、导航定位、右键菜单等绝大多数业务定制场景。如需进一步了解事件机制与编辑配置可继续阅读 LogicFlow 实例 API 文档 中的其他章节。【免费下载链接】LogicFlowA flow chart editing framework focus on business customization. 专注于业务自定义的流程图编辑框架支持实现脑图、ER图、UML、工作流等各种图编辑场景。项目地址: https://gitcode.com/GitHub_Trending/lo/LogicFlow创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门