SwiftUI Graphics 是一份关于 SwiftUI 高级视觉效果的技能文档,主要覆盖 Metal 着色器、视觉特效、Liquid Glass 与 Canvas 绘制。文档定位为进阶内容,基础动画部分由 swiftui-motion 技能覆盖,本文只保留精炼规则,深入内容放在 references/ 目录中。
用途与 API 选择 文档提供一棵决策树,按需求选择 API:像素级颜色操作用 .colorEffect(ShaderLibrary....);像素位置或扭曲用 .distortionEffect(ShaderLibrary....);需要整层叠加(混合着色器与背景)用 .layerEffect(ShaderLibrary....);需要几何上下文的视图修饰符用 .visualEffect { content, geometry in };自定义绘制(路径、渐变)用 Canvas { context, size in };iOS 26+ 玻璃拟态用 .glassEffect() / GlassEffectContainer;性能导出用带 .opaque(true) 的 Canvas。默认升级顺序为:内置修饰符 → .visualEffect → Canvas → Metal 着色器,仅当效果是逐像素且需要动画时才使用着色器。
Metal 着色器 SwiftUI 通过 iOS 17 引入的三个修饰符绑定 Metal Shading Language(MSL):.colorEffect、.distortionEffect、.layerEffect。开发者在应用 target 中编写 .metal 文件,用 [[ stitchable ]] 标记函数,SwiftUI 会自动通过 ShaderLibrary.<functionName>(...) 生成 Swift 绑定。每个应用 target 一个库。着色器在 GPU 上以原生分辨率运行,参数从 Swift 以 .float、.float2、.color、.image 传入。仅支持 iOS 17+,更早版本需回退到渐变、模糊或 Canvas。 三个槽位接收的数据不同:.colorEffect 接收 (position, color),返回变换后的颜色,不采样邻域;.distortionEffect 接收 (position),返回新的采样位置,像素移动但颜色不变;.layerEffect 接收 (position, SwiftUI::Layer layer),返回最终颜色,可在 maxSampleOffset 范围内任意采样,开销最大。
示例配方 文档给出三个可运行示例。涟漪 .layerEffect:点击产生沿正弦波位移邻近像素的效果,代码包含 RippleView 与 Ripple.metal,说明 [[ stitchable ]] 暴露函数、前两个参数由 SwiftUI 注入、maxSampleOffset 决定可采样范围(低估会裁剪,高估浪费 GPU)。全息 .colorEffect:油膜彩虹微光,由时间或滚动偏移驱动,保留亮度使暗部保持暗,代码包含 Holographic.metal 与 HolographicCard,其中 2.094 和 4.188 是 2π/3 与 4π/3,用于把三条正弦波分散到 RGB 相位。CRT 扫描线:复古 CRT 效果,含扫描线、闪烁与轻微色差,代码为 CRT.metal 与 .colorEffect 调用;文档指出真正的色差(偏移 R/B 采样位置)需升级为 .layerEffect,上述版本只是着色,小尺寸下读起来像 CRT。
.visualEffect(iOS 17+) 该修饰符暴露视图的 GeometryProxy,可在任意坐标空间中响应其 frame,无需 GeometryReader 样板代码。示例展示在 ScrollView + LazyVStack 中根据 proxy.frame(in: .scrollView).minY 计算缩放与透明度。适用场景包括视差卡片、滚动驱动缩放、粘性揭示(用 .offset(y: max(0, -y)) 钳制位置)。文档强调 .visualEffect 纯视觉:返回的几何是只读的,不能触发状态更新,不要在其中写 @State。
Liquid Glass(iOS 26) 系统级玻璃拟态,具有自适应深度与形变过渡,内置于操作系统并在系统层优化。示例用 @Namespace 与 .glassEffect(.regular)、.glassEffectID("hero", in: glassNS),并用 #available(iOS 26.0, *) 做版本判断,旧版本回退到 .background(.ultraThinMaterial)。对于应作为一个整体形变的分组表面(如悬停时拆分为独立胶囊的标签栏),用 GlassEffectContainer(spacing: 12) 包裹。iOS 26 之前:静态玻璃用 .background(.ultraThinMaterial),形变过渡回退到基于材质视图的 matchedGeometryEffect(见 swiftui-motion)。深入内容见 references/liquid-glass-deep.md。
Canvas(SwiftUI 原生绘制) 矢量绘制 API,支持路径、渐变、文本、混合模式,无需离开 SwiftUI。示例 SparkleField 用 Canvas 绘制随机星点。要动画,需包裹在 TimelineView(.animation) 中使闭包按帧率重跑;TimelineView(.animation) 按屏幕刷新率重绘,用 .animation(minimumInterval: 0.1) 可降低动画速度以省电。深入内容见 references/canvas-swiftui.md。
性能考量 文档列出各效果成本:.colorEffect 低(逐像素、简单数学、无邻域访问);.distortionEffect 中(采样成本,无分支很关键);.layerEffect 高(整层访问,可任意采样);Canvas 配合 TimelineView 视绘制数量与复杂度而定;.glassEffect 中高(GPU 重,现代设备尚可)。规则包括:避免在同一视图上叠加超过一个 .layerEffect(每个都是一次完整渲染通道);在动画子树外预计算静态部分(渐变、路径);优化前先用 Instruments 的 GPU Frame Capture 与 Metal System Trace 做性能分析。
反模式 文档列出四类反模式。一是叠加多个 .colorEffect 修饰符,每个都是独立渲染通道,应改为一个着色器一次完成所有操作。二是 Canvas 在每次状态变化时重绘,Canvas 会在任意祖先状态变化时重跑,应通过 EquatableView 或 TimelineView 隔离。三是着色器内硬编码颜色值,会迫使重新编译才能改色,应从 Swift 传入。四是到处使用 .glassEffect,Liquid Glass 开销大且过度使用视觉嘈杂,应保留给 hero / chrome 表面。
快速参考 文档给出加载指引:Metal 配方深入见 references/metal-recipes.md;Liquid Glass 模式与 iOS 26 细节见 references/liquid-glass-deep.md;Canvas 绘制模式见 references/canvas-swiftui.md;基础动画见 ../swiftui-motion/SKILL.md;基础见 ../motion-principles/SKILL.md;移动端 UX(iOS)见 ../mobile-principles/SKILL.md;桌面端 UX(macOS)见 ../desktop-principles/SKILL.md。来源列出 twostraws/Inferno、Treata11/iShader、jamesrochabrun/ShaderKit、raphaelsalaja/metallurgy、eleev/swiftui-new-metal-shaders、Apple Metal Shading Language Spec 与 Apple Shader 文档。