X6 滤镜(Filter)完全指南:内置滤镜 API、参数详解与自定义滤镜注册

发布时间:2026/9/17 2:28:55

X6 滤镜(Filter)完全指南:内置滤镜 API、参数详解与自定义滤镜注册 X6 滤镜Filter完全指南内置滤镜 API、参数详解与自定义滤镜注册【免费下载链接】X6 JavaScript diagramming library that uses SVG and HTML for rendering.项目地址: https://gitcode.com/GitHub_Trending/x6/X6导读本文围绕 X6GitHub_Trending/x6/X6的滤镜注册表展开系统讲解如何在节点/边的attrs中通过filter属性为元素施加 SVG 滤镜覆盖 11 个内置滤镜的参数语义与底层实现、graph.defineFilter()与Graph.registerFilter()的完整调用方式以及如何自定义一个符合类型签名的滤镜并注册使用。读完本文你将能够为图元素实现投影阴影、模糊、灰阶、高亮描边等视觉特效并掌握扩展自定义滤镜的标准流程。一、认识 X6 的滤镜机制X6 是基于 SVG 与 HTML 渲染的图编辑引擎其所有内置滤镜都注册在filterRegistry中定义于 src/registry/filter/index.ts实现代码位于 src/registry/filter 目录。该注册表通过Registry.create({ type: filter })创建并在模块加载时将 src/registry/filter/main.ts 导出的 11 个预设滤镜一次性注册filterRegistry.register(presets, true)。在 X6 中任何可被 SVG 渲染的元素节点、边、标签等都可以通过attrs中的filter特殊属性引用一个滤镜。filter属性在 src/registry/attr/filter.ts 中被定义为export const filter: AttrDefinition { qualify: ObjectExt.isPlainObject, set(filter, { view }) { return url(#${view.graph.defineFilter(filter as any)}) }, }可以看到它的两个关键行为qualify只有传入普通对象isPlainObject时才触发滤镜解析这保证了filter: none之类的字符串写法不会走滤镜逻辑set把对象交给view.graph.defineFilter(...)生成filter元素的 id并将最终属性值转换为url(#id)引用。对应测试位于tests/registry/attr/filter.spec.ts其中验证了qualify只接受普通对象且set会输出url(#test-filter)形式的引用。1.1filter属性对象的结构filter属性对象包含两个字段字段类型必填说明namestring是滤镜名称必须是已注册滤镜的名字内置或自定义argsobject否传给滤镜定义函数的参数对象具体键随滤镜而异const rect graph.addNode({ x: 40, y: 40, width: 80, height: 30, attrs: { body: { filter: { name: dropShadow, args: { dx: 2, dy: 2, blur: 3, }, }, }, }, })1.2 修改已创建元素的滤镜节点创建之后也可以通过attr()方法修改或重新指定滤镜rect.attr(body/filter, { name: dropShadow, args: { dx: 2, dy: 2, blur: 3, }, })1.3 通过graph.defineFilter()直接获取滤镜 IDfilter属性对象的方式适合直接在attrs中使用如果你需要复用同一个滤镜或想手动把滤镜 id 拼进字符串可以调用graph.defineFilter(...)实现于 src/graph/graph.ts它返回filter元素的 id然后以url(#id)或#id的形式引用const filterId graph.defineFilter({ name: dropShadow, args: { dx: 2, dy: 2, blur: 3, }, }) rect.attr(body/filter, #${filterId})defineFilter的底层实现在 src/graph/defs.tsDefsManager.filter若未显式提供id会按filter-${name}-${cid}-${hashcode(JSON.stringify(options))}生成稳定 id相同参数重复调用不会重复创建filter节点从filterRegistry中取出对应定义函数fn并执行fn(options.args || {})得到filter内部标记字符串自动为filter元素附加默认属性x: -1, y: -1, width: 3, height: 3, filterUnits: objectBoundingBox即滤镜作用区域放大为元素包围盒的 3 倍并居中避免阴影、描边等效果被裁切可通过FilterOptions.attrs覆盖这些默认值若滤镜名称未注册则调用filterRegistry.onNotFound(name)处理。FilterOptions的类型定义同样位于 src/graph/defs.tsexport type FilterOptions (FilterNativeItem | FilterManualItem) { id?: string attrs?: SimpleAttrs }二、内置滤镜详解X6 内置了 11 个滤镜全部实现于 src/registry/filter 目录且大多数参考了 CSS 同名滤镜函数的行为。下文逐一给出参数表、源码要点与适用场景。2.1 dropShadow —— 投影阴影实现文件src/registry/filter/drop-shadow.ts参数名类型默认值说明dxnumber0阴影在 X 轴的偏移量dynumber0阴影在 Y 轴的偏移量colorstringblack阴影颜色blurnumber4文档表记0见下文说明阴影的模糊半径opacitynumber1阴影的透明度说明文档参数表将blur默认值记为0而当前源码getNumber(args.blur, 4)的实际默认值为4。使用时应以“不传即采用源码默认值”为准。实现亮点源码针对浏览器兼容性做了双路径渲染——优先使用SVGFEDropShadowElementfeDropShadow单标签实现当该特性不可用时自动降级为feGaussianBlur feOffset feFlood feComposite feMerge组合实现等效效果从而保证老浏览器上阴影依然可见。export function dropShadow(args: DropShadowArgs {}) { const dx getNumber(args.dx, 0) const dy getNumber(args.dy, 0) const color getString(args.color, black) const blur getNumber(args.blur, 4) const opacity getNumber(args.opacity, 1) return SVGFEDropShadowElement in window ? filterfeDropShadow stdDeviation${blur} dx${dx} dy${dy} flood-color${color} flood-opacity${opacity} //filter.trim() : filter feGaussianBlur inSourceAlpha stdDeviation${blur} / feOffset dx${dx} dy${dy} resultoffsetblur / feFlood flood-color${color} / feComposite in2offsetblur operatorin / feComponentTransferfeFuncA typelinear slope${opacity} //feComponentTransfer feMergefeMergeNode/feMergeNode inSourceGraphic//feMerge /filter.trim() }适用场景节点/边增加立体层次感、悬浮选中态提示。2.2 blur —— 高斯模糊实现文件src/registry/filter/blur.ts参数名类型默认值说明xnumber2X 轴方向的模糊程度ynumber-Y 轴方向的模糊程度缺省时与 X 轴保持一致实现即文档中给出的示例代码当args.y存在且为有限数值时stdDeviation输出为[x, y]二元数组否则退化为单个x值。export interface BlurArgs { x?: number y?: number } export function blur(args: BlurArgs {}) { const x getNumber(args.x, 2) const stdDeviation args.y ! null isFinite(args.y) ? [x, args.y] : x return filterfeGaussianBlur stdDeviation${stdDeviation}//filter.trim() }适用场景视觉失焦、待激活元素弱化、蒙层背景。2.3 grayScale —— 灰阶实现文件src/registry/filter/gray-scale.ts参数名类型默认值说明amountnumber1灰阶程度取值[0-1]0无灰度1全灰实现基于feColorMatrix typematrix的亮度加权矩阵Rec. 709 亮度系数0.2126 / 0.7152 / 0.0722并按amount在“原图”与“全灰”之间线性插值const a 0.2126 0.7874 * (1 - amount) const b 0.7152 - 0.7152 * (1 - amount) const c 0.0722 - 0.0722 * (1 - amount) // ... 生成 20 个值的矩阵字符串适用场景禁用态节点、历史版本灰显。2.4 sepia —— 褐色老照片实现文件src/registry/filter/sepia.ts参数名类型默认值说明amountnumber1褐色程度取值[0-1]0无褐色1全褐色同样基于feColorMatrix typematrix使用经典的 sepia 转换矩阵系数0.393 / 0.769 / 0.189等并随amount线性插值。适用场景复古主题图、归档/历史数据展示。2.5 saturate —— 饱和度实现文件src/registry/filter/saturate.ts参数名类型默认值说明amountnumber1饱和度取值[0-1]实现将amount换算为feColorMatrix typesaturate的values${1 - amount}。注意amount 1表示饱和度降为0完全去饱和amount 0表示保持原图不变——数值越大越灰与直觉相反使用时需注意文档参数表中1被描述为“完全去饱和”源码注释亦如此标注。适用场景强调/弱化元素对比。2.6 hueRotate —— 色相旋转实现文件src/registry/filter/hue-rotate.ts参数名类型默认值说明anglenumber0色相旋转角度度实现为feColorMatrix typehueRotate values${angle}0表示不旋转360表示旋转一整圈回到原点。适用场景主题换色、状态色区分。2.7 invert —— 反色实现文件src/registry/filter/invert.ts参数名类型默认值说明amountnumber1反色度取值[0-1]0无反色1完全反色实现为feComponentTransfer中 R/G/B 三个通道均使用typetable tableValues${amount} ${1 - amount}的查表插值。适用场景暗色主题下的元素适配、强调翻转。2.8 brightness —— 明亮度实现文件src/registry/filter/brightness.ts参数名类型默认值说明amountnumber1明亮度取值[0-1]0全暗1全亮实现为 R/G/B 三通道feFuncR/G/B typelinear slope${amount}直接对通道做线性缩放。适用场景明暗对比、暗色置灰背景。2.9 contrast —— 对比度实现文件src/registry/filter/contrast.ts参数名类型默认值说明amountnumber1对比度取值[0-1]0全暗1全亮实现为线性变换slopeamount, intercept0.5-amount/2围绕 50% 灰阶中点缩放像素值从而提升或降低对比度。适用场景强调边界、弱化视觉噪音。2.10 highlight —— 高亮描边实现文件src/registry/filter/highlight.ts参数名类型默认值说明colorstringred高亮颜色widthnumber1高亮外框的宽度blurnumber0模糊半径opacitynumber1透明度实现链路feFlood生成高亮色 →feMorphology operatordilate沿形状外扩width像素 →feComposite in裁剪出外扩环带 →feGaussianBlur可选模糊 →feBlend与原始图形混合。适用场景节点选中高亮、告警提示、命中搜索目标。2.11 outline —— 边框描边实现文件src/registry/filter/outline.ts参数名类型默认值说明colorstringblue边框颜色widthnumber1边框宽度marginnumber2边框与元素之间的边距opacitynumber1透明度实现通过两次feMorphology膨胀得到内外半径innerRadius margin、outerRadius margin width再用feComposite operatorxor对内外环带求差得到镂空边框最后feMerge将边框与原始图形叠加且边框与图形之间保留margin间隙不会盖住元素本体。适用场景虚线/实体选中框之外的描边强调、分组标签框。2.12 内置滤镜速查表滤镜名称对应源码主要参数典型用途dropShadowdrop-shadow.tsdx, dy, color, blur, opacity阴影层次blurblur.tsx, y高斯模糊grayScalegray-scale.tsamount灰阶禁用态sepiasepia.tsamount复古褐色saturatesaturate.tsamount饱和度调整hueRotatehue-rotate.tsangle色相旋转invertinvert.tsamount反色brightnessbrightness.tsamount明暗调整contrastcontrast.tsamount对比度调整highlighthighlight.tscolor, width, blur, opacity高亮描边outlineoutline.tscolor, width, margin, opacity镂空边框三、自定义滤镜定义与注册当内置滤镜不满足需求时可以自定义滤镜。滤镜的本质是一个函数接收参数对象args返回filter标签内部的 SVG 标记字符串。类型签名定义于 src/registry/filter/index.tsexport type FilterDefinitionT (args: T) string即DefinitionT (args: T) string。3.1 编写一个滤镜定义函数以官方文档示例的高斯模糊为例与源码 blur.ts 一致export interface BlurArgs { x?: number y?: number } export function blur(args: BlurArgs {}) { const x getNumber(args.x, 2) const stdDeviation args.y ! null isFinite(args.y) ? [x, args.y] : x return filter feGaussianBlur stdDeviation${stdDeviation}/ /filter .trim() }编写要点默认值处理仓库统一使用 util.ts 提供的getNumber(value, defaultValue)与getString(value, defaultValue)二者都会过滤null/undefined与非有限数值Number.isFinite保证参数缺失或非法时不产出undefined字符串只返回内部标记函数返回值会被 X6 用Markup.sanitize(markup)清洗后包进一个自动生成的filter元素见 defs.ts因此你只需返回fe*原语组合返回值会被 trim源码实现统一.trim()保持输出整洁。3.2 注册自定义滤镜使用Graph.registerFilter(name, definition)静态方法注册对应filterRegistry.register见 graph.tsimport { Graph } from antv/x6 Graph.registerFilter(blur, blur) // 注册后即可像内置滤镜一样使用 graph.addNode({ x: 40, y: 40, width: 80, height: 30, attrs: { body: { filter: { name: blur, args: { x: 2, y: 2 }, }, }, }, })注册表同时提供了配套的静态方法便于管理滤镜生命周期Graph.registerFilter(name, definition, overwrite?)—— 注册第三个参数可控制是否覆盖已存在的同名滤镜Graph.unregisterFilter(name)—— 注销见 graph.ts未注册的名称在defineFilter时会命中filterRegistry.onNotFound(name)的处理逻辑因此务必先注册再使用。3.3 自定义滤镜的完整示例下面实现一个“内阴影inner shadow”滤镜演示多原语组合import { Graph } from antv/x6 interface InnerShadowArgs { dx?: number dy?: number blur?: number color?: string opacity?: number } function innerShadow(args: InnerShadowArgs {}) { const dx args.dx ?? 0 const dy args.dy ?? 0 const blur args.blur ?? 4 const color args.color ?? rgba(0,0,0,0.5) const opacity args.opacity ?? 0.6 return feOffset dx${dx} dy${dy}/ feGaussianBlur stdDeviation${blur} resultoffset-blur/ feComposite operatorout inSourceGraphic in2offset-blur resultinverse/ feFlood flood-color${color} flood-opacity${opacity} resultcolor/ feComposite operatorin incolor in2inverse resultshadow/ feComposite operatorover inshadow in2SourceGraphic/ .trim() } Graph.registerFilter(innerShadow, innerShadow) graph.addNode({ x: 120, y: 120, width: 120, height: 60, attrs: { body: { fill: #fff, stroke: #8f8f8f, filter: { name: innerShadow, args: { dx: 2, dy: 2, blur: 6 } }, }, }, })提示以上滤镜内部使用了标准 SVG 滤镜原语feOffset、feGaussianBlur、feComposite、feFlood是编写自定义滤镜时最常用的组合手段。四、实践官方示例中的滤镜用法仓库内置了每个滤镜的交互式演示页位于 site/src/api/filter每个子目录包含index.tsx演示组件、settings.tsx参数面板、index.less样式。以 site/src/api/filter/drop-shadow/index.tsx 为例演示页在节点上叠加了背景色、描边和dropShadow滤镜并通过this.node.attr({ body: { filter: { name: dropShadow, args: { ...args } } } })实时响应参数面板的调整settings.tsx 提供了color、dx、dy、blur、opacity五个可调项滑杆范围dx/dy/blur为0-20opacity为0.05-1颜色为取色器可直接在本地运行site应用体验不同参数组合的实时效果。演示页的节点本身也演示了一个实用细节body与label同时更新——滤镜作用于body而文本颜色用Color.invert(args.color, true)动态取反保证标签在任意滤镜/底色上仍可读。五、常见问题与使用建议1. 滤镜作用区域被裁切怎么办X6 默认将filter的x/y设为-1、width/height设为3相对objectBoundingBox即 3 倍包围盒并居中。若阴影/描边特别宽仍被裁切可通过defineFilter的attrs覆盖graph.defineFilter({ name: dropShadow, args: { dx: 20, dy: 20, blur: 10 }, attrs: { x: -2, y: -2, width: 5, height: 5 }, })2. 如何复用同一个滤镜实例defineFilter以name args的 JSON 哈希生成稳定 id相同参数只在defs中创建一次filter重复调用零额外开销适合大量节点共用同一套阴影/描边。3. 为什么filter属性必须传对象而不能传字符串attr/filter的qualify只认普通对象见 filter.ts。若需直接用字符串 id请改用graph.defineFilter(...)拿到 id 后拼接url(#id)或#id赋值。4. 滤镜名拼写错了会发生什么defineFilter在注册表中找不到对应定义时会触发filterRegistry.onNotFound(name)。请确保name与注册名完全一致或先通过Graph.registerFilter完成注册。5. 性能建议滤镜尤其带模糊的feGaussianBlur属于 GPU 开销较高的 SVG 特性。对高频动画的节点建议只对选中/悬浮态的少数元素施加滤镜优先复用已生成的滤镜 id避免在frame循环中频繁改变args导致filter重建。六、相关文档与源码索引滤镜属性在属性系统文档中的位置attr 文档目录本指南对应的filter属性说明见属性注册表文档内置滤镜注册入口src/registry/filter/index.ts、src/registry/filter/main.ts滤镜实现src/registry/filter11 个文件逐一对应内置滤镜参数工具函数src/registry/filter/util.tsfilter属性解析src/registry/attr/filter.ts 与对应测试tests/registry/attr/filter.spec.tsfilter元素生成与去重src/graph/defs.ts、入口 src/graph/graph.ts交互演示 site/src/api/filter【免费下载链接】X6 JavaScript diagramming library that uses SVG and HTML for rendering.项目地址: https://gitcode.com/GitHub_Trending/x6/X6创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/9/17 2:23:53

Docker核心原理与实战:从虚拟机对比到MySQL/Redis部署全解析

1. 面试官为什么必问“Docker 和虚拟机到底有什么区别”这个问题几乎每场Docker相关面试都会出现,面试官不是真想听你背一遍“容器更轻量、启动更快”这两句话,而是想通过这个题目判断你到底有没有真的用过Docker,还是只是看了几篇入门博客。…

2026/9/17 2:23:53

HDFS入门到实践:架构、命令、读写流程与排查

1. 为什么是HDFS:从架构优势看它的不可替代性1.1 单机存储不够用了,HDFS补的是什么短板在传统单机环境中存文件,最简单的方式是挂块磁盘、做好RAID,再用Samba或NFS共享出去。数据量在几百GB以内这种方案确实够用,但等业…

2026/9/17 3:28:58

Vue 3 核心 API 解析:defineComponent 与 defineAsyncComponent 实战指南

前两天帮同事排查一个奇怪的问题:他写了一个 Vue 3 组件,函数命名也对、组件也正常注册了,但在 IDE 里 props 和 emits 完全没有任何类型提示。他第一反应是“是不是 Volar 插件坏了”?我让他把代码发过来一看——他确实用了 defi…

2026/9/17 3:28:58

交换机端口模式详解:Access、Trunk、Hybrid与VLAN标签转发

我第一次在交换机上敲下port link-type trunk的时候,心里其实没底:为什么一个物理口非得规定成某种模式?后来复习计算机网络,再看到“端口模式”四个字,又差点把它和 TCP 端口号搞混。这个概念卡了我很久,直…

2026/9/17 3:28:58

Windows文件复制进阶:从copy到robocopy,掌握健壮的文件同步与备份命令

直接在Windows命令提示符里敲copy去复制文件,很多人第一反应就是“这不就够用了吗”。但等你真正面对几万个文件、跨磁盘拷贝、增量备份、日志记录这些需求的时候,copy命令那点能力立马就显得捉襟见肘。所以Windows其实内置了一个很多人没用过的“搬家神…

2026/9/17 3:23:58

仿美团外卖菜单实战:数据模型与RecyclerView联动全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/16 12:52:37

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/17 0:03:13

WiFi密码安全测试:从原理到实战的字典暴力破解指南

1. 写在前面:我为什么要研究WiFi密码这件事先交代一下背景。我身边有不少朋友,家里的WiFi密码常年是"12345678"或者"88888888",问就是"好记"。直到有一次,隔壁邻居蹭网蹭到我家路由器后台都进不去&…

2026/9/17 0:03:13

redis-py服务控制与监控函数实战:从ping到slowlog的巡检指南

我用 redis-py 写了快五年的业务代码,坦白说,真正让我觉得这个客户端“像一个成熟工具箱”的,不是 get/set 那套基本操作,而是它那批专门做服务控制与状态监控的辅助函数。日常开发里,大家把redis.Redis(host..., deco…

2026/9/17 0:03:13

SpringBoot+Vue3实现中小企业设备管理系统开发实践

1. 项目概述与核心价值中小企业设备管理系统是制造业、服务业等领域的基础信息化工具。传统设备管理往往依赖Excel表格或纸质记录,存在数据孤岛、流程混乱、维护成本高等痛点。这套基于Java SpringBootVue3MyBatis的技术方案,通过前后端分离架构实现了设…

2026/9/16 22:55:57

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/16 22:56:09

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/16 22:56:16

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码