- 数据可视化
- 前端
- 图表库
【免费下载链接】G6
♾ A Graph Visualization Framework in JavaScript.
边过滤镜(EdgeFilterLens)是 G6 内置的透镜类探索工具:它会在画布上绘制一个圆形透镜,只有"被关注"的边才会在透镜范围内显示,其余边在该范围内被隐藏。本文将基于 EdgeFilterLens 官方示例 与 插件源码,完整讲解它的配置项、四种边显示条件、动态更新方法及底层实现原理,帮助你在大规模关系图中快速聚焦局部连接关系。
插件概述:透镜内只保留你关注的边
边过滤镜插件可以将关注的边保留在过滤镜范围内,其他边将在该范围内不显示。它是一个重要的可视化探索工具,可以帮助用户聚焦于特定区域的边关系。其典型使用场景包括:
- 需要聚焦查看局部区域的边关系;
- 在复杂网络中突出显示特定节点之间的连接。
从实现上看,插件在画布的transient(临时)图层上创建了一个圆形透镜(Circle),并把聚焦区域内的节点、边以克隆副本的方式叠加渲染到透镜之上;而原始画布中的其他元素则被透镜本身遮盖,从而在视觉上实现"只显示范围内关注边"的效果。
快速上手:两种初始化方式
边过滤镜插件已经内置注册在 G6 中,无需额外引入即可使用。最简单的配置方式是用字符串简写直接启用:
const graph = new Graph({ plugins: ['edge-filter-lens'], });需要调整参数时,使用配置对象形式:
const graph = new Graph({ plugins: [ { type: 'edge-filter-lens', trigger: 'pointermove', // 跟随鼠标移动 r: 60, // 设置透镜半径 nodeType: 'both', // 边的显示条件 }, ], });创建实例后调用graph.render()即可看到效果:鼠标在画布上移动时,一个圆形透镜会跟随指针,透镜内的边被"点亮",透镜外的边被遮挡隐藏。
配置项详解
以下为 EdgeFilterLens 插件的完整配置项(与 EdgeFilterLens 官方手册 及源码中 EdgeFilterLensOptions 接口 保持一致):
| 属性 | 描述 | 类型 | 默认值 | 必选 |
|---|---|---|---|---|
| type | 插件类型 | string | edge-filter-lens | ✓ |
| key | 插件的唯一标识,可用于获取插件实例或更新插件选项 | string | - | |
| trigger | 移动透镜的方式 | pointermove|click|drag | pointermove | |
| r | 透镜的半径 | number | 60 | |
| maxR | 透镜的最大半径(仅在scaleRBy为wheel时生效) | number | 画布宽高最小值的一半 | |
| minR | 透镜的最小半径(仅在scaleRBy为wheel时生效) | number | 0 | |
| scaleRBy | 缩放透镜半径的方式 | wheel | wheel | |
| nodeType | 边显示的条件 | both|source|target|either | both | |
| filter | 过滤出始终不在透镜中显示的元素 | (id, elementType) => boolean | () => true | |
| style | 透镜(圆形)的样式 | object | 见下文 style 表 | |
| nodeStyle | 在透镜中节点的样式 | [NodeStyle] |(datum) => NodeStyle | { label: false } | |
| edgeStyle | 在透镜中边的样式 | [EdgeStyle] |(datum) => EdgeStyle | { label: true } | |
| preventDefault | 是否阻止默认事件 | boolean | true |
以上默认值在源码的 defaultOptions 中有完整定义:
static defaultOptions: Partial<EdgeFilterLensOptions> = { trigger: 'pointermove', r: 60, nodeType: 'both', filter: () => true, style: { lineWidth: 2 }, nodeStyle: { label: false }, edgeStyle: { label: true }, scaleRBy: 'wheel', preventDefault: true, };trigger:透镜如何移动
pointermove:透镜始终跟随鼠标移动(默认);click:鼠标点击画布时,透镜移动到点击位置;drag:通过拖拽方式移动透镜。
源码在 bindEvents 中按触发方式分别注册事件:click与drag走CLICK监听;pointermove走POINTER_MOVE监听;drag额外监听DRAG_START/DRAG/DRAG_END三个事件,并借助isLensDragging标志位判断拖拽是否命中透镜内部。
nodeType:边的显示条件
这是插件最核心的过滤逻辑,四种取值决定了什么样的边会在透镜中显示(源码见 getFocusElements):
both:只有起始节点和目标节点都在透镜中时,边才会显示;source:只有起始节点在透镜中时,边才会显示;target:只有目标节点在透镜中时,边才会显示;either:起始节点或目标节点任一在透镜中时,边就会显示。
对应源码的判定逻辑为:
const isSourceFocus = focusNodeIds.includes(source); const isTargetFocus = focusNodeIds.includes(target); switch (this.options.nodeType) { case 'both': return isSourceFocus && isTargetFocus; case 'either': return isSourceFocus !== isTargetFocus; case 'source': return isSourceFocus && !isTargetFocus; case 'target': return !isSourceFocus && isTargetFocus; }从源码可以看出,either模式实际实现为"异或"(isSourceFocus !== isTargetFocus),即恰好一个端点落入透镜的边才会显示——这与"只要有一个端点在透镜中就显示"的语义在数学上等价于两边端点不同时落入的边。需要完整展示端点跨透镜的连接关系时,either是最直观的选择。
r / minR / maxR / scaleRBy:透镜半径控制
r:透镜初始半径,默认 60;minR/maxR:半径缩放的范围限制,仅在scaleRBy: 'wheel'时生效,maxR默认取画布宽高最小值的一半;scaleRBy: 'wheel':通过滚轮缩放透镜半径。
滚轮缩放的实现位于 scaleRByWheel:当滚轮事件位置与透镜中心距离小于半径时,按DELTA = 0.05的步进因子放大或缩小半径,并通过Math.max(minR, Math.min(maxR, r * ratio))钳制在[minR, maxR]区间内,随后重绘透镜与聚焦元素。
filter:永久排除指定元素
filter接收一个回调(id, elementType) => boolean,返回false的元素将始终不出现在透镜中(即使它位于透镜范围内)。元素类型elementType取值为node/edge/combo。例如排除某条特定边:
plugins: [ { type: 'edge-filter-lens', filter: (id, elementType) => !(elementType === 'edge' && id === 'edge-100'), }, ],源码在 getFilterData 中先用filter对model.getData()返回的 nodes / edges / combos 分别过滤,再在此基础上计算聚焦元素。
style:圆形透镜样式
style控制透镜圆形本身的样式,可用的样式属性如下:
| 属性 | 描述 | 类型 | 默认值 |
|---|---|---|---|
| fill | 填充颜色 | string | Pattern | null | #fff |
| stroke | 描边颜色 | string | Pattern | null | #000 |
| opacity | 整体透明度 | number | string | 1 |
| fillOpacity | 填充透明度 | number | string | 0.8 |
| strokeOpacity | 描边透明度 | number | string | - |
| lineWidth | 线宽度 | number | string | 2 |
| lineCap | 线段端点样式 | butt|round|square | - |
| lineJoin | 线段连接处样式 | miter|round|bevel | - |
| shadowColor | 阴影颜色 | string | - |
| shadowBlur | 阴影模糊程度 | number | - |
| shadowOffsetX | 阴影 X 方向偏移 | number | - |
| shadowOffsetY | 阴影 Y 方向偏移 | number | - |
源码中的 defaultLensStyle 提供了基准样式(白色填充、黑色描边、透明度 0.8,zIndex: -Infinity保证透镜位于底层),defaultOptions.style额外补充了lineWidth: 2,最终通过Object.assign({}, defaultLensStyle, options.style)合并。
nodeStyle / edgeStyle:透镜内元素样式
透镜内的节点和边是原始元素的克隆副本,可以通过nodeStyle/edgeStyle单独定制,从而在聚焦时放大节点、高亮描边、显示标签等。两者均支持静态对象或函数形式(函数接收元素数据datum,返回样式对象),源码通过 getElementStyle 根据元素类型分发:
private getElementStyle(elementType: ElementType, datum: ElementDatum) { const styler = elementType === 'node' ? this.options.nodeStyle : this.options.edgeStyle; if (typeof styler === 'function') return styler(datum); return styler; }完整示例:从官方 demo 看实际用法
官方示例 demo/basic.js 使用远程关系数据集(relations.json)构建了一张含大量边的关系图,并启用了边过滤镜:
import { Graph } from '@antv/g6'; fetch('https://assets.antv.antgroup.com/g6/relations.json') .then((res) => res.json()) .then((data) => { const graph = new Graph({ container: 'container', data, autoFit: 'view', node: { style: { size: 16 }, palette: { field: (datum) => Math.floor(datum.style?.y / 60), }, }, edge: { style: { label: false, labelText: (d) => d.data.value?.toString(), stroke: '#ccc', }, }, plugins: [ { key: 'edge-filter-lens', type: 'edge-filter-lens', }, ], }); graph.render(); });结合 API 文档的完整配置形态
API 配置参考 中给出了包含全部可选参数(含r、trigger、nodeType、minR、maxR、scaleRBy及三层样式)的完整形态,可作为生产环境的配置模板:
const graph = new Graph({ // ...数据与元素配置 plugins: [ { type: 'edge-filter-lens', key: 'edge-filter-lens', r: 80, // 透镜半径 trigger: 'pointermove', // 触发方式 nodeType: 'both', // 边显示条件 minR: 50, // 最小半径 maxR: 150, // 最大半径 scaleRBy: 'wheel', // 缩放方式 style: { fill: '#f0f5ff', fillOpacity: 0.4, stroke: '#1d39c4', strokeOpacity: 0.8, lineWidth: 1.5, }, nodeStyle: { size: 35, fill: '#d6e4ff', stroke: '#2f54eb', lineWidth: 2, labelFontSize: 14, labelFontWeight: 'bold', labelFill: '#1d39c4', }, edgeStyle: { stroke: '#1d39c4', lineWidth: 2, strokeOpacity: 0.8, }, }, ], });自定义透镜与聚焦元素样式
以下示例演示如何自定义透镜外观以及透镜内节点/边的展示效果(源自 官方手册 的"自定义样式"一节):
const graph = new Graph({ plugins: [ { type: 'edge-filter-lens', r: 80, style: { fill: '#f0f5ff', // 透镜区域的填充颜色 fillOpacity: 0.6, // 填充区域的透明度 stroke: '#7e3feb', // 透镜边框改为紫色 strokeOpacity: 0.8, // 边框的透明度 lineWidth: 1.5, // 边框的线宽 }, nodeStyle: { size: 24, // 放大节点 fill: '#7e3feb', // 紫色填充 stroke: '#5719c9', // 深紫色描边 lineWidth: 1, // 细边框 label: true, // 显示标签 labelFill: '#ffffff', // 白色文字 labelFontSize: 14, // 放大文字 labelFontWeight: 'bold', // 文字加粗 }, edgeStyle: { stroke: '#8b9baf', // 灰色边 lineWidth: 2, // 加粗边线 label: true, // 显示标签 labelFill: '#5719c9', // 深紫色文字 opacity: 0.8, // 适当的透明度 }, }, ], });动态更新插件配置:updatePlugin
边过滤镜的参数可以在运行时通过graph.updatePlugin动态修改,无需重建图实例。官方 demo 中的控制面板(dat.GUI)演示了三种常用参数的实时切换:
graph.updatePlugin({ key: 'edge-filter-lens', trigger: 'click', // 可切换为 pointermove / click / drag }); graph.updatePlugin({ key: 'edge-filter-lens', scaleRBy: 'wheel', // 可切换为 wheel / unset }); graph.updatePlugin({ key: 'edge-filter-lens', nodeType: 'both', // 可切换为 source / target / both / either });修改style/nodeStyle/edgeStyle等嵌套对象时,需要把整组对象传入:
graph.updatePlugin({ key: 'edge-filter-lens', nodeStyle: { size: 35, fill: '#d6e4ff' }, });源码中 update 方法 的实现是先unbindEvents()解绑旧事件,再合并新选项(this.r = options.r ?? this.r保留未显式修改的半径),最后bindEvents()按新 trigger/scaleRBy 重新绑定事件,从而实现无缝热更新。destroy方法则会解绑事件并销毁透镜及所有克隆形状。
源码视角:透镜的渲染与回收机制
从 EdgeFilterLens 类 可以梳理出插件运行的完整链路:
- 创建透镜:首次触发时在
transient图层new Circle({ style })并挂载,之后通过lens.update({ x, y, size: r * 2 })移动与缩放; - 计算聚焦元素:
getFocusElements以透镜中心为圆心、r为半径,用distance(positionOf(datum), origin) < r判定节点是否落入透镜,再按nodeType过滤边; - 克隆渲染:
renderFocusElements对聚焦的节点与边执行shape.cloneNode()生成克隆副本,追加到 transient 图层并套用nodeStyle/edgeStyle,同时用Map<ID, Element>缓存克隆形状,仅同步属性变化(Object.entries(shape.attributes)逐项比对更新); - 回收清理:每一帧渲染后,将不在聚焦集合内的克隆形状
destroy()并从缓存中移除,避免内存泄漏。
这一"克隆叠加"的设计使得原始元素本身不被修改,透镜移开后画布立即恢复原状,非常适合在静态布局图、时序关系图等场景中做即席探查。该插件与其他插件的组合方式可参考 插件总览 与 扩展机制说明。
小结
边过滤镜通过"透镜内克隆叠加、透镜外物理遮盖"的机制,为复杂网络提供了一种低成本的局部聚焦方案。配置上只需关注四个关键决策点:trigger(如何移动)、r / minR / maxR(透镜范围)、nodeType(边显示条件)与nodeStyle / edgeStyle(聚焦态样式)。若需在运行中调整,统一通过graph.updatePlugin({ key: 'edge-filter-lens', ... })完成。更多可运行示例与源码,可继续查阅 示例入口 与 插件源码。
- 数据可视化
- 前端
- 图表库
【免费下载链接】G6
♾ A Graph Visualization Framework in JavaScript.
相关推荐
Hermes WebUI Transparent Stream:让 Agent 执行活动按时间线逐行呈现的显示模式实现
Hermes WebUI Transparent Stream:让 Agent 执行活动按时间线逐行呈现的显示模式实现 本文基于 Hermes WebUI 仓库
数据可视化前端图表库G6 边过滤镜插件 EdgeFilterLens 完全指南:配置、原理与实战
G6 边过滤镜插件 EdgeFilterLens 完全指南:配置、原理与实战 边过滤镜(EdgeFilterLens)是 G6 图形可视化框架内置的交互式探索插
数据可视化前端图表库RemoveWindowsAI:批量移除 Windows 11 Copilot 与 Recall 等 AI 功能的实操笔记
RemoveWindowsAI:批量移除 Windows 11 Copilot 与 Recall 等 AI 功能的实操笔记 Windows 11 从 25H2
数据可视化前端图表库
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考