与锚点(Anchor)完全指南:定制边与节点连接位置的实战方案)
X6 连接点ConnectionPoint与锚点Anchor完全指南定制边与节点连接位置的实战方案【免费下载链接】X6 JavaScript diagramming library that uses SVG and HTML for rendering.项目地址: https://gitcode.com/GitHub_Trending/x6/X6锚点Anchor与连接点ConnectionPoint是 X6 图编辑引擎中决定边从节点的哪个位置出发、落到哪个位置的两级机制锚点确定参考线瞄准的落点方向连接点负责在节点图形上计算边真正的起点/终点。本篇指南以 X6 教程 connection-point.zh.md 为主线结合源码与配套示例讲解两者的概念、全局与局部两种配置方式、全部内置类型、参数语义以及自定义扩展方法帮助你为流程图、拓扑图等场景定制出稳定、精准的特殊连线。从示例现象出发为什么连接位置可以固定在 X6 的教程配套示例 multi/index.tsx 中源节点和多个目标节点之间连了三条边拖动节点时你会发现边与节点的连接位置保持不变且多条边之间存在间隔。这与默认连线总是从节点边缘最近处出发的现象完全不同。实现这一效果的关键正是同时指定了anchor锚点与connectionPoint连接点graph.addEdge({ source: { cell: source, anchor: { name: right, args: { dy: -10 } }, // 锚点节点右侧中心再上移 10px connectionPoint: anchor, // 连接点直接用锚点位置 }, target: { cell: target, anchor: { name: left, args: { dy: -10 } }, connectionPoint: anchor, }, attrs: { line: { stroke: #8f8f8f, strokeWidth: 1 }, }, })三条边分别使用dy: -10、dy: 0、dy: 10的锚点偏移量于是每条边都在固定的上下间隔处连接节点拖拽节点时连接点始终钉在相对位置上——这正是锚点 连接点组合能力的直观体现。锚点与连接点一条参考线上的两个环节要理解连接机制需要把边的端点如何确定拆成两步锚点Anchor确定参考线的瞄准点。默认锚点为center元素中心。连接点ConnectionPoint负责计算参考线与节点图形的交点。默认值为boundary与元素边框的交点。因此一条边端点的完整计算流程是从起点元素的锚点到终点元素的锚点拉一条参考线再用connectionPoint指定的计算方法求参考线与元素图形的交点该交点就是边的起点/终点。当节点移动时锚点跟随节点移动连接点由参考线与图形实时求交从而保证连接位置与节点相对关系稳定。从源码结构看X6 将这两种机制分别注册为两套独立的内置定义集合锚点定义位于 src/registry/node-anchor/main.ts导出bbox、orth、node-center、middle-side等连接点定义位于 src/registry/connection-point/main.ts导出bbox、rect、boundary、anchor。两种配置方式全局默认与单边覆盖锚点和连接点都支持两种配置入口且创建边时在source/target中指定的配置优先级更高。方式一在connecting中全局配置适用于整个画布统一采用某种连接风格的场景const graph new Graph({ connecting: { sourceAnchor: { name: right, // 锚点落在节点右侧中心再向上偏移 10px args: { dy: -10 }, }, targetAnchor: { name: right, // 目标锚点同样使用右侧中心上移 10px args: { dy: -10 }, }, connectionPoint: anchor, // 连接点直接取锚点位置不参与求交 }, })从 src/graph/options.ts 的默认配置可以看到X6 出厂时即设置了connecting: { anchor: center, // 默认锚点元素中心 edgeAnchor: ratio, // 默认边锚点 connectionPoint: boundary, // 默认连接点与元素边框求交 router: normal, connector: normal, },也就是说如果你不配置任何锚点/连接点边的端点就是元素中心到元素中心的参考线与双方边框的交点。sourceAnchor/targetAnchor比anchor更精细可分别控制源端与目标端的锚点sourceConnectionPoint/targetConnectionPoint同理见 options.ts。方式二在创建边时局部指定优先级更高graph.addEdge({ source: { cell: source, anchor: { name: right, args: { dy: -10 }, }, connectionPoint: anchor, // 源端连接点直接使用锚点 }, target: { cell: target, anchor: { name: left, args: { dy: -10 }, }, connectionPoint: anchor, }, })这种写法让每一条边都可以拥有独立的连接策略最适合多边并行、需要错开连接点的场景即本文开头示例的做法。连接点没有参数时还可以简写为字符串例如connectionPoint: boundary锚点同样支持anchor: orth这样的无参简写。内置锚点一览把落点钉在元素的哪个位置X6 内置了 12 种锚点完整定义与参数说明见 node-anchor.zh.md。核心类型如下锚点位置语义关键参数center元素中心点默认值dx/dy偏移支持数字与百分比、rotate是否跟随旋转top/bottom/left/right元素四边中心点同上midSide最靠近边的那一侧中心点padding放大包围盒、direction: H \| V限定水平/垂直方向topLeft/topRight/bottomLeft/bottomRight元素四个角dx/dy偏移、rotateorth正交点与水平/垂直参考线正交paddingnodeCenter节点中心dx/dy其中midSide的就近侧判断逻辑在源码 middle-side.ts 中有完整实现它先取元素包围盒通过bbox.getNearestSideToPoint(refPoint)找到离参考点最近的一侧再返回该侧的中心点若指定direction: H则只在left/right两个侧中心之间选择direction: V则在top/bottom之间选择从而实现只从左右或只从上下连接的约束。锚点同样支持两种配置方式例如全局默认锚点new Graph({ connecting: { anchor: { name: midSide, args: { dx: 10 } }, }, })以及创建后动态修改edge.setSource({ cell: source-id, anchor: { name: midSide, args: { dx: 10 } }, })内置连接点详解四种求交策略连接点决定了参考线与图形哪里相交。X6 提供四种内置实现见 connection-point.zh.mdboundary默认与真实图形边框求交自动识别链接图形的形状并求交例如ellipse会被识别为椭圆求椭圆与直线的交点无法识别的元素如text、path则回退为包围盒求交效果等同于bbox。支持的参数参数类型默认值说明offsetnumber \| Point.PointLike0连接点的偏移量strokedbooleantrue是否考虑图形边框宽度默认会把描边宽度的一半计入insideoutbooleantrue参考线位于图形内部且无交点时是否延长参考线求交extrapolatebooleanfalse参考线位于图形外部且无交点时是否延长参考线求交优先级高于stickystickybooleanfalse无交点时是否使用边框上离参考线最近的点作为交点precisionnumber2交点计算精度针对 Path 分段selectorstringundefined选择器指定用哪个元素的边框求交默认取节点中第一个不在g内的子元素源码 boundary.ts 揭示了其实现要点先把参考线变换到节点本地坐标系调用localLine.intersect(localShape)求交若没有交点且sticky为true则对矩形用getNearestPointToPoint、对椭圆用intersectsWithLineFromCenterToPoint、其余图形用closestPoint取最近点兜底。另外extrapolate为true时会把参考线长度扩展到1e6再求交以覆盖参考线太短够不到图形的情况。anchor直接用锚点作连接点不做任何求交计算直接返回锚点位置可带偏移。这就是本文开头示例连接位置固定不动的关键——绕过了边界求交边端点与锚点完全重合。参数仅offsetnumber \| Point.PointLike默认0。其实现见 anchor.ts源码还额外支持aligntop/right/bottom/left与alignOffset用于把参考线对齐到指定方向后再取端点这在固定端口类连接中很实用。bbox与包围盒求交计算参考线与元素未旋转包围盒的交点参数为offset与stroked默认false即默认不考虑描边宽度。实现见 bbox.ts先取view.getBBoxOfElement(magnet)若stroked为真则用描边宽度的一半inflate包围盒再与参考线求交无交点时退回line.end。rect与旋转后的矩形区域求交与bbox的区别在于使用元素旋转后的矩形区域求交参数同为offset与stroked默认false。适合节点带旋转角度的场景。配置示例创建边时指定无参可简写为字符串const edge graph.addEdge({ source: { cell: source-id, connectionPoint: { name: boundary, args: { sticky: true }, }, }, target: { cell: target-id, connectionPoint: boundary, }, })全局配置与动态修改方式与锚点一致new Graph({ connecting: { connectionPoint: { name: boundary, args: { sticky: true } }, }, }) edge.setSource({ cell: source-id, connectionPoint: { name: boundary, args: { sticky: true } }, })理解 offset 与描边连接点的沿参考线平移语义连接点的offset参数与锚点的dx/dy语义不同。从 util.ts 的offset实现可以看出offset是沿参考线方向的平移量——它先算出交点与参考线起点之间的距离length然后调用p1.move(p2, -Math.min(tx, length - 1))把交点沿参考线反方向移动且最大不超过线长。因此offset为正数时连接点从交点沿参考线向源端方向回退传Point.PointLike如{ x, y }时y分量先用于把参考线平移offset.y像素x分量再沿平移后的线回退当stroked: trueboundary 默认开启时源码会把描边宽度的一半叠加进offset确保边端点停在图形边缘而非边框线中央。自定义锚点与连接点完全掌控连接语义内置类型不满足需求时X6 允许注册自定义实现注册后即可像内置类型一样按名称使用。自定义连接点连接点定义是接收参考线与节点视图、返回交点坐标的函数type DefinitionT ( line: Line, // 参考线 view: NodeView, // 连接的节点视图 magnet: SVGElement, // 连接的节点上的元素 args: T, // 参数 ) Point注册并全局启用Graph.registerConnectionPoint(custom-connection-point, (line, view, magnet, args) { // 自定义求交逻辑返回 Point return line.end }) new Graph({ connecting: { connectionPoint: custom-connection-point, }, })自定义锚点锚点定义签名如下详见 node-anchor.zh.mdtype DefinitionT ( this: EdgeView, nodeView: NodeView, magnet: SVGElement, ref: Point.PointLike | SVGElement, args: T, type: Edge.TerminalType, ) Point注册并全局启用Graph.registerAnchor(custom-anchor, (nodeView, magnet, ref, args, type) { // 自定义锚点计算返回 Point return ref as Point }) new Graph({ connecting: { anchor: { name: custom-anchor }, }, })结语选择合适组合的两条原则回顾整篇内容可以提炼出两条实战原则需要钉死连接位置端口、错开多边时锚点指定精确落点配合dx/dy偏移错开连接点用anchor直接取锚点即教程示例 multi/index.tsx 的做法需要随形贴合自适应节点形状、旋转时锚点用center/midSide连接点用默认的boundary真实图形求交或rect旋转后矩形求交配合sticky/extrapolate/offset处理参考线无交点与描边等边界情况。两种机制都支持全局connecting配置与单边source/target覆盖且后者优先级更高必要时还可通过Graph.registerAnchor与Graph.registerConnectionPoint注册完全自定义的实现。更完整的参数表可继续查阅 node-anchor.zh.md 与 connection-point.zh.md将这两级机制配合使用即可覆盖从固定端口到任意形状贴合的全部连线定制需求。【免费下载链接】X6 JavaScript diagramming library that uses SVG and HTML for rendering.项目地址: https://gitcode.com/GitHub_Trending/x6/X6创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考