news 2026/9/24 16:48:26

G6 边过滤镜(EdgeFilterLens)插件实战:聚焦局部边关系,隔离复杂网络噪声

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
G6 边过滤镜(EdgeFilterLens)插件实战:聚焦局部边关系,隔离复杂网络噪声
  • 数据可视化
  • 前端
  • 图表库

【免费下载链接】G6

♾ A Graph Visualization Framework in JavaScript.

项目地址:https://gitcode.com/gh_mirrors/g6/G6
点击查看免费下载

边过滤镜(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插件类型stringedge-filter-lens
key插件的唯一标识,可用于获取插件实例或更新插件选项string-
trigger移动透镜的方式pointermove|click|dragpointermove
r透镜的半径number60
maxR透镜的最大半径(仅在scaleRBywheel时生效)number画布宽高最小值的一半
minR透镜的最小半径(仅在scaleRBywheel时生效)number0
scaleRBy缩放透镜半径的方式wheelwheel
nodeType边显示的条件both|source|target|eitherboth
filter过滤出始终不在透镜中显示的元素(id, elementType) => boolean() => true
style透镜(圆形)的样式object见下文 style 表
nodeStyle在透镜中节点的样式[NodeStyle] |(datum) => NodeStyle{ label: false }
edgeStyle在透镜中边的样式[EdgeStyle] |(datum) => EdgeStyle{ label: true }
preventDefault是否阻止默认事件booleantrue

以上默认值在源码的 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 中按触发方式分别注册事件:clickdragCLICK监听;pointermovePOINTER_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 中先用filtermodel.getData()返回的 nodes / edges / combos 分别过滤,再在此基础上计算聚焦元素。

style:圆形透镜样式

style控制透镜圆形本身的样式,可用的样式属性如下:

属性描述类型默认值
fill填充颜色string | Pattern | null#fff
stroke描边颜色string | Pattern | null#000
opacity整体透明度number | string1
fillOpacity填充透明度number | string0.8
strokeOpacity描边透明度number | string-
lineWidth线宽度number | string2
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 配置参考 中给出了包含全部可选参数(含rtriggernodeTypeminRmaxRscaleRBy及三层样式)的完整形态,可作为生产环境的配置模板:

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 类 可以梳理出插件运行的完整链路:

  1. 创建透镜:首次触发时在transient图层new Circle({ style })并挂载,之后通过lens.update({ x, y, size: r * 2 })移动与缩放;
  2. 计算聚焦元素getFocusElements以透镜中心为圆心、r为半径,用distance(positionOf(datum), origin) < r判定节点是否落入透镜,再按nodeType过滤边;
  3. 克隆渲染renderFocusElements对聚焦的节点与边执行shape.cloneNode()生成克隆副本,追加到 transient 图层并套用nodeStyle/edgeStyle,同时用Map<ID, Element>缓存克隆形状,仅同步属性变化(Object.entries(shape.attributes)逐项比对更新);
  4. 回收清理:每一帧渲染后,将不在聚焦集合内的克隆形状destroy()并从缓存中移除,避免内存泄漏。

这一"克隆叠加"的设计使得原始元素本身不被修改,透镜移开后画布立即恢复原状,非常适合在静态布局图、时序关系图等场景中做即席探查。该插件与其他插件的组合方式可参考 插件总览 与 扩展机制说明。

小结

边过滤镜通过"透镜内克隆叠加、透镜外物理遮盖"的机制,为复杂网络提供了一种低成本的局部聚焦方案。配置上只需关注四个关键决策点:trigger(如何移动)、r / minR / maxR(透镜范围)、nodeType(边显示条件)与nodeStyle / edgeStyle(聚焦态样式)。若需在运行中调整,统一通过graph.updatePlugin({ key: 'edge-filter-lens', ... })完成。更多可运行示例与源码,可继续查阅 示例入口 与 插件源码。

  • 数据可视化
  • 前端
  • 图表库

【免费下载链接】G6

♾ A Graph Visualization Framework in JavaScript.

项目地址:https://gitcode.com/gh_mirrors/g6/G6
点击查看免费下载
上一篇:抖音视频批量下载器:一键保存高清无水印内容的终极方案
下一篇:在Switch上畅享B站:wiliwili第三方客户端完整安装指南

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

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

Netty 4.1 使用 Protobuf 传输数据:itstack-demo-netty 中级拓展篇二实战解析

文档教程后端 【免费下载链接】CodeGuide :books: 本代码库是作者小傅哥多年从事一线互联网 Java 开发的学习历程技术汇总&#xff0c;旨在为大家提供一个清晰详细的学习教程&#xff0c;侧重点更倾向编写Java核心内容。如果本仓库能为您提供帮助&#xff0c;请给予支持(关注、…

作者头像 李华
网站建设 2026/9/24 16:44:57

Linux驱动01-系统移植

一、系统移植1.1 系统移植介绍① 系统移植主要指在开发板上运行Linux操作系统&#xff0c;涉及硬件驱动开发、Linux系统与硬件设备的兼容适配以及内核层面的编程工作。② 将Linux系统移植到开发板的过程中&#xff0c;需要完成四个关键组件的移植&#xff1a;Bootloader&#x…

作者头像 李华
网站建设 2026/9/24 16:43:44

TVA具身智能运行机理(38):如何推动具身智能产业跨越式发展

前沿技术探索&#xff1a;TVA智能体&#xff08;简称TVA&#xff09; TVA智能体&#xff08;亦称“AI智能体视觉”&#xff09;是依托Transformer架构与“因式智能体”理论构建的新型工业视觉系统&#xff0c;也是当前最具代表性的具身视觉技术之一。它有机融合深度强化学习&a…

作者头像 李华
网站建设 2026/9/24 16:43:12

AI旅游赛道独立开发者怎么切入?4条路径不踩坑

AI旅游市场2026年预计2224亿美元&#xff0c;年增速33.7%&#xff0c;40%旅客已在用AI规划行程。海外Wanderlog积累100万用户&#xff0c;Layla年费49.99美元&#xff0c;已跑通订阅加联盟返佣的双收入模型。但照搬国内会立刻撞墙。 虎嗅网近期复盘的一个踩了五个坑的真实案例&…

作者头像 李华