C# SkiaSharp绘图方法 C#如何使用SkiaSharp进行跨平台2D绘图

来源:这里教程网 时间:2026-02-21 17:42:31 作者:

SkiaSharp 初始化必须调用
SKImageInfo
SKSurface.Create
才能绘图

直接 new

SKCanvas
会抛出
System.NotSupportedException
—— 它没有无参构造函数,也不能独立存在。所有绘图操作必须绑定到一个有效的绘图表面(
SKSurface
)上。

常见做法是:在 Windows Forms 中用

SKBitmap
+
SKSurface.Create
;在 WPF 中用
WriteableBitmap
配合
SKSurface.Create
;在 .NET MAUI 中直接用
SKCanvasView
Canvas
参数。

Windows Forms 示例:
var bitmap = new SKBitmap(width, height); var surface = SKSurface.Create(new SKImageInfo(width, height), bitmap); var canvas = surface.Canvas;
避免在 UI 线程外反复创建
SKSurface
,尤其在动画循环中——应复用
SKSurface
或至少复用
SKBitmap
MAUI 中不要手动 new
SKCanvas
,而是通过
SKCanvasView.PaintSurface
事件的
e.Surface.Canvas
获取

SKPaint
IsAntialias
FilterQuality
决定线条/文字清晰度

默认情况下

SKPaint
抗锯齿关闭、滤镜质量低,绘出的圆弧、斜线、小字号文字容易发虚或出现像素断裂。这不是 bug,是 Skia 的默认性能权衡。

开启抗锯齿:
paint.IsAntialias = true;
(对路径、文字、图像缩放都生效)
提升缩放质量:
paint.FilterQuality = SKFilterQuality.High;
(尤其在
canvas.DrawBitmap
缩放时明显)
文字渲染建议额外设置:
paint.TextEncoding = SKTextEncoding.Utf8;
paint.Typeface = SKTypeface.FromFamilyName("Segoe UI", SKFontStyle.Bold);
注意:高频开关
IsAntialias
本身不耗资源,但开启后绘制路径的 CPU 开销会上升约 15–20%

跨平台字体加载必须用
SKTypeface.FromStream
或嵌入资源

直接传入系统字体名(如

"Arial"
)在 macOS 或 Linux 上大概率失败,.NET MAUI Android/iOS 也受限于沙盒和字体注册机制。SkiaSharp 不走系统字体管理器,它需要字节流或已注册的 typeface。

推荐方式:把 .ttf 文件作为
EmbeddedResource
,运行时用
Assembly.GetExecutingAssembly().GetManifestResourceStream(...)
加载,再传给
SKTypeface.FromStream(stream)
Android 上可访问
/system/fonts/
下字体,但需 root;iOS 不允许读取系统字体路径
MAUI 中不要依赖
SKTypeface.Default
渲染中文——它在非 Windows 平台常 fallback 到无汉字的字体,导致方块
调试技巧:用
typeface.FamilyName
打印确认加载成功,空字符串表示加载失败

释放
SKBitmap
SKSurface
SKTypeface
必须显式调用
Dispose()

这些类型包装了非托管内存(Skia 的 native sk_bitmap_t / sk_surface_t),GC 不会自动回收。漏掉

Dispose()
会导致内存缓慢增长,Windows 上可能几 MB/秒,Android 上更容易触发 OOM。

务必用
using
块包裹短期对象:
using var bitmap = new SKBitmap(...); using var surface = SKSurface.Create(...);
SKTypeface
是线程安全且可共享的,建议全局缓存(如
static readonly SKTypeface ChineseFont = LoadMyFont();
),避免重复加载
MAUI 中
SKCanvasView
PaintSurface
事件里拿到的
e.Surface
由框架管理,**不要调用
Dispose()
**;仅自己 new 出来的才需释放
检查泄漏:在 Visual Studio 的“诊断工具”中观察“Native Heap”趋势,或用
dotnet-counters --process-id [pid] Microsoft.Extensions.DependencyInjection:DiagnosticSource
辅助定位

跨平台绘图真正难的不是 API 调用,而是每个平台对资源生命周期、字体路径、DPI 感知的隐式差异。哪怕一行

canvas.DrawRect
,背后涉及 surface 格式兼容性、GPU 后端切换、字体回退链——这些细节不踩一遍坑很难凭文档猜全。

相关推荐