news 2026/9/20 6:39:49

X6 连接点(Connection Point)与锚点完全指南:从边界求交到自定义特殊连线

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
X6 连接点(Connection Point)与锚点完全指南:从边界求交到自定义特殊连线

X6 连接点(Connection Point)与锚点完全指南:从边界求交到自定义特殊连线

【免费下载链接】X6🚀 JavaScript diagramming library that uses SVG and HTML for rendering.项目地址: https://gitcode.com/GitHub_Trending/x6/X6

本指南围绕 X6 图编辑引擎中"边如何吸附到节点"这一核心机制展开,系统讲解锚点(Anchor)与连接点(Connection Point)的概念、计算流程、全局与单边配置方式,并基于仓库源码深入解析boundarybboxrectanchor四种内置连接点与十余种内置锚点的全部参数。读完本文,你将掌握如何让多条连线在节点上保持固定间隔、如何让连线精准吸附任意图形边界,以及如何通过Graph.registerConnectionPoint/Graph.registerAnchor注册自定义连接点与锚点,定制出贴合业务场景的特殊连线。

先看效果:固定连接点的多连线示例

教程章节以一个可交互示例开场(对应源码site/src/tutorial/intermediate/connection-point/multi/index.tsx):当你在画布上拖动节点时,边与节点的连接位置始终保持不变,且多条边之间保留固定间隔。这与默认的连线行为(连接点随节点移动而重算)完全不同。

其实现思路正是本指南的主题:通过给每条边显式指定锚点与连接点,把"连接位置"从"跟随图形变化"转变为"固定在节点上的特定点"

理解锚点与连接点:一条参考线的两端

两个概念的职责划分

X6 用两个独立的概念共同决定边的起点和终点:

  • 锚点(Anchor):边在节点上的"瞄准点"。默认值为center,即元素的几何中心。它只负责"指向哪里",并不直接决定最终的起止点。
  • 连接点(Connection Point):决定"交点怎么算"。默认值为boundary,即与元素边框的交点。

边的绘制过程可以拆解为三步:

  1. 起点元素的锚点终点元素的锚点连一条参考线;
  2. 按照connectionPoint指定的计算方法,求出参考线与元素图形的交点;
  3. 该交点即为边的起点/终点。

更精确地讲(参见 连接点注册表文档):

  • 起点:从第一个路径点(若没有路径点则取终点元素的中心)连参考线到起点元素的锚点,再按指定连接点算法求参考线与图形的交点,即为边的起点;
  • 终点:从最后一个路径点(若没有路径点则取起点元素的中心)连参考线到终点元素的锚点,再按指定连接点算法求交点,即为边的终点。

源码中的计算链路

这条计算流水线在边视图(EdgeView)中按固定顺序执行,见 src/view/edge/index.ts:

  1. findAnchors(vertices):求出源/目标锚点(sourceAnchor/targetAnchor);
  2. findRoutePoints(vertices):求出路由点(路径点);
  3. findConnectionPoints(routePoints, sourceAnchor, targetAnchor):结合锚点与路由点计算最终连接点。

在模型层,src/model/edge.ts 的getTerminalPoint(type)会先判断终点是否为纯坐标点;若绑定的是 Cell,则调用cell.getConnectionPoint(this, type)交给节点侧解析。而全局默认值定义在 src/graph/options.ts 的Connecting配置中:

anchor: 'center', connectionPoint: 'boundary', router: 'normal', connector: 'normal',

使用方式一:在connecting中全局配置

锚点与连接点都可以在图实例的connecting选项中全局配置,所有后续创建的边都会继承该默认值:

const graph = new Graph({ connecting: { // 锚点会在节点右侧中心向上偏移 10px sourceAnchor: { name: 'right', args: { dy: -10, }, }, // 锚点会在节点右侧中心向上偏移 10px targetAnchor: { name: 'right', args: { dy: -10, }, }, // 连接点直接用锚点位置,不再做边界求交 connectionPoint: 'anchor', }, })

这里sourceAnchor/targetAnchor对应节点锚点(NodeAnchor),connectionPoint对应连接点(ConnectionPoint)。配置对象由name(内置类型名或自定义注册名)与args(该类型支持的参数)组成;当无参数时可直接写成字符串简写,例如connectionPoint: 'boundary'

需要留意的是,src/graph/options.ts 还提供了更细粒度的覆盖项:sourceConnectionPoint/targetConnectionPointsourceEdgeAnchor/targetEdgeAnchor(边锚点 EdgeAnchor),可用于区分起点与终点采用不同算法。

使用方式二:在source/target中单边配置(优先级更高)

创建边时,可以在sourcetarget中分别指定锚点与连接点,单边配置的优先级高于connecting中的全局配置

graph.addEdge({ source: { cell: source, anchor: { name: 'right', args: { dy: -10, }, }, connectionPoint: 'anchor', }, target: { cell: target, anchor: { name: 'left', args: { dy: -10, }, }, connectionPoint: 'anchor', }, })

边创建完成后,还可以通过edge.setSource/edge.setTarget动态修改连接点(见 connection-point 注册表文档):

edge.setSource({ cell: 'source-id', connectionPoint: { name: 'boundary', args: { sticky: true, }, }, })

上述示例中锚点固定为right/left并偏移 10px、连接点直接取锚点(connectionPoint: 'anchor'),正是"多边固定连接位置、彼此保持间隔"效果的通用写法——连接点不再参与求交,边的起止点即锚点本身。

四种内置连接点详解

X6 提供四种内置连接点算法(实现统一注册于 src/registry/connection-point/main.ts 与 src/registry/connection-point/index.ts):

名称说明
boundary默认值,与连接元素的实际图形边界求交
bbox与连接元素的包围盒求交
rect与连接元素的旋转后矩形区域求交
anchor直接以锚点作为连接点

boundary:智能识别图形边界

boundary会自动识别连接元素的真实几何形状(如<ellipse>会按椭圆求交、矩形按矩形求交),无法识别的元素(如text<path>)则退化为包围盒求交,行为等同于bbox。其实现位于 src/registry/connection-point/boundary.ts。

参数名类型必填默认值说明
offsetnumber \| Point.PointLike0连接点的偏移量
strokedbooleantrue是否考虑图形描边宽度
insideoutbooleantrue参考线位于图形内部且无交点时,是否延长参考线求交
extrapolatebooleanfalse参考线位于图形外部且无交点时,是否延长参考线求交;优先级高于sticky
stickybooleanfalse参考线位于图形外部且无交点时,是否取边界上距离参考线最近的点作为连接点
precisionnumber2交点计算精度
selectorstringundefined选择器,用于指定节点内某个子元素,取其边界求交;默认取节点内第一个非<g>的子元素

结合源码看几个关键行为:

  • insideout:当锚点在图形内部、参考线与图形无交点时,若insideout === false且参考线起点被图形包围盒包含,则直接返回锚点(见boundary.tslocalBBox.containsPoint(localRef)分支);
  • extrapolate:为true时将参考线长度延长到1e6再求交(localLine.setLength(1e6)),保证远距离也能命中边界;
  • sticky:无交点时对矩形调用getNearestPointToPoint、对椭圆调用intersectsWithLineFromCenterToPoint、其余图形调用closestPoint,把连接点"粘"到边界最近点;
  • stroked:为true时通过 src/registry/connection-point/util.ts 的getStrokeWidth读取stroke-width,把连接点再外扩半个描边宽度;
  • precision:对Path类图形,路径会被细分成小段(getSegmentSubdivisions)后求交,精度越高分段越细。

提示:boundary对复杂path图形的支持在仓库示例 examples/src/pages/edge/sticky-point.tsx 中有完整演示(sticky: true, extrapolate: true配合circleellipsepolygonpolyline、自定义path图标等形状)。

anchor:锚点即连接点

anchor连接点直接返回参考线端点(锚点位置),支持以下参数:

参数名类型必填默认值说明
offsetnumber \| Point.PointLike0连接点偏移量

其实现 src/registry/connection-point/anchor.ts 还额外支持两个可选参数:align'top' | 'right' | 'bottom' | 'left')与alignOffset,可将参考线对齐到指定方向后再取端点,源码与测试(tests/registry/connection-point/anchor.spec.ts)中均有对应逻辑。

bbox 与 rect

  • bbox:求参考线与元素未旋转包围盒的交点。参数:offset(默认0)、stroked(默认false,注意与boundary的默认值不同)。
  • rect:求参考线与元素旋转后矩形区域的交点,参数与bbox一致(offset默认0stroked默认false)。适合元素带有angle旋转角度的场景。

两种算法的参数均以对象形式传入:

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, }, }, // 简写:connectionPoint: 'boundary' }, })

内置锚点(NodeAnchor)速查

锚点决定了参考线从节点的哪个位置引出。X6 内置 12 种锚点,完整参数见 NodeAnchor 注册表文档,注册入口在 src/registry/node-anchor/main.ts。

名称说明
center元素中心点(默认值)
top/bottom/left/right元素上/下/左/右边缘的中点
midSide距离最近的那条边的中点
topLeft/topRight/bottomLeft/bottomRight元素四个角
orth正交点
nodeCenter节点中心点

其中centertopbottomleftright、四个角点共用一套参数:

参数名类型必填默认值说明
dxnumber \| string0X 轴偏移,支持绝对偏移与百分比相对偏移
dynumber \| string0Y 轴偏移,支持绝对偏移与百分比相对偏移
rotatebooleanfalse是否使用随节点旋转的包围盒,默认不考虑旋转角度

midSide额外支持:

参数名类型必填默认值说明
paddingnumber0沿边方向偏移的像素距离
direction'H' \| 'V'-限定连接方向,如设为H则只连接节点左右侧中点,根据相对位置自动判断

orth支持padding(默认0);nodeCenter支持dxdy(默认均为0)。

锚点同样支持在创建边时指定、事后用edge.setSource/edge.setTarget修改、以及在connecting中全局配置:

const edge = graph.addEdge({ source: { cell: 'source-id', anchor: { name: 'midSide', args: { dx: 10 }, }, }, target: { cell: 'target-id', anchor: 'orth', // 无参数时简写 }, }) // 全局默认 new Graph({ connecting: { anchor: { name: 'midSide', args: { dx: 10 }, }, }, })

自定义连接点与自定义锚点

当内置类型无法满足需求时,X6 允许注册任意数量的自定义实现,注册后即可像内置类型一样按名称使用。

自定义连接点

连接点定义是一个返回Point的函数:

export type Definition<T> = ( line: Line, // 参考线 view: NodeView, // 所连接节点的视图 magnet: SVGElement, // 所连接节点上的元素 args: T, // 参数 ) => Point

完成定义后注册到全局注册表(内部实现为 src/registry/connection-point/index.ts 的connectionPointRegistry):

Graph.registerConnectionPoint('custom-connection-point', (line, view, magnet, args) => { // 返回连接点坐标 return new Point(0, 0) })

之后即可直接按名称使用:

new Graph({ connecting: { connectionPoint: 'custom-connection-point', }, })

自定义锚点

锚点定义同样是一个函数,签名为:

export type Definition<T> = ( this: EdgeView, // 边视图 nodeView: NodeView, // 节点视图 magnet: SVGElement, // magnet 元素 ref: Point.PointLike | SVGElement, // 参考点/元素 args: T, // 参数 type: Edge.TerminalType, // 边端点类型(source / target) ) => Point

注册与使用方式与连接点一致:

Graph.registerAnchor('custom-anchor', (nodeView, magnet, ref, args, type) => { // 返回锚点坐标 return new Point(0, 0) }) new Graph({ connecting: { anchor: { name: 'custom-anchor', }, }, })

小结

锚点与连接点是 X6 边渲染链路中决定"边从哪里出发、落在哪里"的两个关键环节:锚点负责瞄准,连接点负责求交。通过connecting全局配置与source/target单边配置(后者优先级更高),配合boundarysticky/extrapolate/selector等参数、midSide/right等锚点的dx/dy偏移,即可稳定实现多连线等间隔、吸附任意形状边界等特殊连线效果;当内置能力不够时,还可通过注册函数的方式完全自定义连接点与锚点的计算逻辑。

建议继续阅读仓库内配套文档以获得完整参数矩阵与可交互示例:ConnectionPoint 注册表文档、NodeAnchor 注册表文档,以及边的基础用法 edge 教程。

【免费下载链接】X6🚀 JavaScript diagramming library that uses SVG and HTML for rendering.项目地址: https://gitcode.com/GitHub_Trending/x6/X6

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/20 22:05:58

继电器切换AD620增益电路设计与高频失真抑制

简介&#xff1a;本资源是一份面向电子工程专业学生、嵌入式开发者及硬件设计初学者的电压可控正弦波放大电路设计详解文档&#xff0c;聚焦模拟电路核心能力训练&#xff0c;解决信号动态增益调节、低失真放大与负电源构建等实际工程问题。文档以AD620精密仪表放大器为核心&am…

作者头像 李华
网站建设 2026/9/19 22:58:59

景星建材高德评分升至4.4分,见证南宁建材供应链服务口碑

近日&#xff0c;高德地图页面显示&#xff0c;景星建材综合评分更新至4.4分。其中&#xff0c;用户行为分4.4分&#xff0c;用户评价分4.4分&#xff0c;并获得高德大数据认证。对于一家建材供应服务商来说&#xff0c;地图评分不只是一个数字。它背后反映的是客户是否真实搜索…

作者头像 李华
网站建设 2026/9/20 4:11:15

网络存储系统开发:前端交互与数据库表结构设计实践

简介&#xff1a;面向计算机及相关专业毕业设计的网络存储系统设计与实现论文&#xff0c;重点围绕用户界面与数据库设计展开&#xff0c;系统介绍了分布式存储技术背景、HTML网页操作技术、系统核心功能及数据存储方案。论文以作者实际参与的网络存储系统项目为基础&#xff0…

作者头像 李华