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或至少复用
SKBitmapMAUI 中不要手动 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 后端切换、字体回退链——这些细节不踩一遍坑很难凭文档猜全。
