前言
我们在前面的章节讨论了 DrawScope。但有时候,DrawScope 提供的通用 API 无法满足我们对极致视觉效果的追求,比如复杂的着色器(Shaders)、滤镜(Filters)或者底层的 Path 运算。
由于 Compose Multiplatform (CMP) 底层就是 Skia,我们完全可以“穿透”抽象层,直接与 Skia 对话。
一、 获取 NativeCanvas 的入场券
在 Compose 的绘制逻辑中,你可以通过以下方式拿到底层的 Canvas 对象:
Canvas(modifier = Modifier.fillMaxSize()) {
drawIntoCanvas { canvas ->
val nativeCanvas = canvas.nativeCanvas
// 现在你可以调用 Skia 的 C++ 指令映射了!
}
}
- Android 上:
nativeCanvas返回的是android.graphics.Canvas。 - CMP(Desktop/iOS/Web)上:返回的是
org.jetbrains.skia.Canvas。
二、 Skia 级的功能增强
当你拿到原生 Canvas 后,你可以解锁以下“禁术”:
- Runtime Shaders (AGSL): 编写类似于 GLSL 的着色器代码,在像素级别控制光影效果(如流光溢彩、波浪纹)。
- 高级 Path 运算: 直接调用 Skia 的 Path 混合、裁剪和复杂描边算法。
- 颜色滤镜 (ColorFilter): 使用 Skia 内置的矩阵滤镜实现电影级的调色。
三、 实战案例:跨平台 Shader 动效
利用我们在本项目中学到的 Native 调用 思想:
- 在
commonMain定义绘制接口。 - 利用 Skiko 提供的
org.jetbrains.skia.*类库。 - 编写一套 100% 共享的 Skia 绘图指令,在 Android 和 iOS 上渲染出完全一致的高级动效。
四、 性能警告
穿透抽象是有代价的:
- 状态管理失效:当你绕过 Compose API 直接操作
nativeCanvas时,Compose 无法自动追踪你的状态变化。你必须手动触发invalidate。 - 跨端差异:虽然 CMP 使用 Skia,但不同平台的显卡驱动(Driver)对特定 Shader 的支持程度可能不同。
五、 职业进阶建议
如果你能掌握 Skia 的原生调用,你将具备开发以下产品的能力:
- 跨端图形设计软件(如类似 Figma 的工具)。
- 高性能图表库。
- 高度自定义的游戏引擎 UI。
🏗️ 源码关键点
androidx.compose.ui.graphics.drawscope.drawIntoCanvasorg.jetbrains.skia.Canvas(CMP 专属)
结语
直接调用 Skia 是 Compose 开发的“最高权限”。它让 Kotlin 拥有了直接操控显卡的能力。
下一篇,我们将讨论图形 API 的跨端适配:Metal (iOS) vs Vulkan (Android) vs OpenGL (Web)。