Avalonia 使用 DrawingContext 在 OnRender 中进行跨平台高性能 2D 绘制,基于 SkiaSharp 构建向量指令并光栅化;需缓存资源、避免频繁 Push/Pop、原点在左上角且单位为 DIP。

Avalonia 使用 DrawingContext 进行自定义绘制,主要在控件的 OnRender 方法中完成,其底层基于 SkiaSharp(默认渲染后端),提供跨平台、高性能的 2D 绘图能力。它不是直接操作像素,而是构建绘图指令列表,由 Skia 引擎最终光栅化。
在 OnRender 中获取并使用 DrawingContext
所有继承自 Visual 的类(如 Control、Shape、自定义 Panel)均可重写 OnRender 方法:
- 必须调用基类实现:`base.OnRender(context)` 通常需放在开头,确保子元素正常绘制(除非你完全接管)
-
context 是临时对象:仅在
OnRender调用期间有效,不可缓存或跨帧复用 - 坐标系原点在左上角,单位为设备无关像素(DIP),自动适配缩放和高 DPI
常用绘图操作与对应 API
DrawingContext 提供分层绘制能力,常见操作包括:
-
绘制几何图形:`DrawGeometry(brush, pen, geometry)` —— 支持
RectangleGeometry、EllipseGeometry、PathGeometry等 -
绘制文本:`DrawText(formattedText, point)` —— 需先用
FormattedText构建带样式的文本布局 -
绘制图像:`DrawImage(bitmap, rect, opacity: 1.0)` —— 支持
IBitmap(如Bitmap实例) -
应用变换:通过
PushTransform+Matrix.CreateScale/Translate/Rotate实现局部坐标系变换 -
裁剪区域:`PushClip(geometry)` 限定后续绘制范围,匹配后需
PopClip
性能与注意事项
高效使用 DrawingContext 需注意以下关键点:
-
避免在 OnRender 中创建资源:如
Brush、Pen、FormattedText应预先创建并缓存(例如在构造函数或OnAttachedToVisualTree中) - 减少 Push/Pop 调用次数:每次变换或裁剪都会增加绘制指令开销,尽量合并操作
-
慎用透明度和混合模式:非 1.0 的
opacity或自定义CompositingMode可能触发离屏渲染,影响性能 -
不支持即时重绘控制:Avalonia 自动管理渲染时机(脏区检测 + 合成),手动调用
InvalidateVisual()触发重绘即可
底层渲染链路简述
Avalonia 的绘图流程为:OnRender → DrawingContext 记录指令 → Scene 树收集所有视觉节点的绘制命令 → 渲染线程交由 SkiaRenderer(基于 SkiaSharp)执行光栅化 → 输出到窗口表面。这意味着:
- 所有
DrawingContext操作本质是构建向量指令,非立即像素操作 - 无 Canvas.Children 类似 WPF 的“子元素集合”,绘图完全由代码逻辑驱动
- 若需更底层控制(如直接 Skia 绘图),可继承
SkiaDrawingContext或使用ISkiaGpu,但会失去跨平台抽象层保障











