SkiaSharp是一个跨平台2D图形API,用于.NET平台,基于Google's Skia Graphics库(skia.org网站). 它提供了一个全面的2D API,可以跨移动、服务器和桌面模型来渲染图像。该图形库可实现获取指定坐标像素值、绘制2d图形、绘制文字(必须有相应字库支持)、创建缩略图等,微软是大力支持的。
可见此地址:
https://docs.microsoft.com/zh-cn/dotnet/api/skiasharp
首先是想熟悉下SkiaSharp的操作,另外呢,想基于SkiaSharp来做跨平台的UI渲染器,一直没有动手,在搜集资料,现在基本搜集的差不多了,所以,就找点例子,学学,也挺有趣的。
一个时钟的效果
大概是以下的样子,也挺简单的,就是对度数是要计算的,用到的方法,也就画圆和画路径以及画文本几个方法。
然后,根据时间,自动转动时钟的指针。
自从毕业后,就没有做过这样的案例了。但是,上手了,感觉还是很欣喜的。
Wpf 和 SkiaSharp
新建一个WPF项目,然后,Nuget包即可
Install-Package SkiaSharp.Views.WPF -Version 2.88.0
其中核心逻辑是这部分,会以我设置的60FPS来刷新当前的画板。
skContainer.PaintSurface += SkContainer_PaintSurface;
_ = Task.Run(() =>
{while (true){try{Dispatcher.Invoke(() =>{skContainer.InvalidateVisual();});_ = SpinWait.SpinUntil(() => false, 1000 / 60);//每秒60帧}catch{break;}}
});
时钟逻辑
/// <summary>/// 一个简单版的时钟/// </summary>public class DrawClock{public SKPoint centerPoint;public int Radius = 0;public int HAND_TRUNCATION;public int HOUR_HAND_TRUNCATION;public int HAND_RADIUS;public int TIPS;/// <summary>/// 渲染/// </summary>public void Render(SKCanvas canvas, SKTypeface Font, int Width, int Height){centerPoint = new SKPoint(Width / 2, Height / 2);this.Radius = (int)(centerPoint.Y - 50);HAND_TRUNCATION = Width / 25;HOUR_HAND_TRUNCATION = Width / 10;HAND_RADIUS = this.Radius + 15;TIPS = this.Radius - 40;canvas.Clear(SKColors.SkyBlue);DrawCircle(canvas, Font);DrawCenter(canvas, Font);DrawHands(canvas, Font);DrawTimeNumber(canvas, Font);DrawTips(canvas, Font);using var paint = new SKPaint{Color = SKColors.Black,IsAntialias = true,Typeface = Font,TextSize = 20};using var paint2 = new SKPaint{Color = SKColors.Blue,IsAntialias = true,Typeface = Font,TextSize = 24};string msg = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss:fff:ffffff}";string tishi = " WPF SkiaSharp 自绘时钟 基础代码";string by = $"by 蓝创精英团队";canvas.DrawText(msg, 0, 30, paint);canvas.DrawText(tishi, 450, 30, paint);canvas.DrawText(by, 600, 400, paint2);}/// <summary>/// 画一个圆/// </summary>public void DrawCircle(SKCanvas canvas, SKTypeface Font){using var paint = new SKPaint{Color = SKColors.Black,Style = SKPaintStyle.Stroke,IsAntialias = true,StrokeWidth = 2};canvas.DrawCircle(centerPoint.X, centerPoint.Y, Radius, paint);}/// <summary>/// 时钟的核心/// </summary>public void DrawCenter(SKCanvas canvas, SKTypeface Font){using var paint = new SKPaint{Color = SKColors.Black,Style = SKPaintStyle.Fill,IsAntialias = true,StrokeWidth = 2};canvas.DrawCircle(centerPoint.X, centerPoint.Y, 5, paint);}private void DrawHand(SKCanvas canvas, SKTypeface Font, int times, bool isHour = false){var angle = Math.PI * 2 * (times / (double)60) - Math.PI / 2;var handRadius = isHour ? this.Radius - HAND_TRUNCATION - HOUR_HAND_TRUNCATION : this.Radius - HAND_TRUNCATION;using var paint = new SKPaint{Color = (DateTimeOffset.Now.Second % 4 <= 1) ? SKColors.Red : SKColors.Green,Style = SKPaintStyle.Fill,StrokeWidth = 2,IsStroke = true,StrokeCap = SKStrokeCap.Round,IsAntialias = true};var path = new SKPath();path.MoveTo(centerPoint);path.LineTo((float)(centerPoint.X + Math.Cos(angle) * handRadius), (float)(centerPoint.Y + Math.Sin(angle) * handRadius));path.Close();canvas.DrawPath(path, paint);}/// <summary>/// 画时针/// </summary>public void DrawHands(SKCanvas canvas, SKTypeface Font){var time = DateTime.Now;var hour = time.Hour > 12 ? time.Hour - 12 : time.Hour;DrawHand(canvas, Font, hour * 5 + time.Minute / 60 * 5, true);DrawHand(canvas, Font, time.Minute, false);DrawHand(canvas, Font, time.Second, false);}/// <summary>/// 画时间点/// </summary>public void DrawTimeNumber(SKCanvas canvas, SKTypeface Font){using var paint = new SKPaint{Color = SKColors.Black,IsAntialias = true,Typeface = Font,TextSize = 24};for (int i = 1; i <= 12; i++){var angle = Math.PI / 6 * (i - 3);var number = i.ToString();var numberTextWidth = paint.MeasureText(number);canvas.DrawText(number, (float)(centerPoint.X + Math.Cos(angle) * HAND_RADIUS - numberTextWidth / 2), (float)(centerPoint.Y + Math.Sin(angle) * HAND_RADIUS + 24 / 3), paint);}}/// <summary>/// 画提示信息/// </summary>public void DrawTips(SKCanvas canvas, SKTypeface Font){using var paint = new SKPaint{Color = SKColors.Black,IsAntialias = true,Typeface = Font,TextSize = 20};var now = DateTime.Now;//年月日var Date = $"{now.Year}/{now.Month}/{now.Day}";var DateTextWidth = paint.MeasureText(Date);var angle = Math.PI / 6 * (6 - 3);canvas.DrawText(Date, (float)(centerPoint.X + Math.Cos(angle) * TIPS - DateTextWidth / 2), (float)(centerPoint.Y + Math.Sin(angle) * TIPS), paint);//PM AMvar amOrPm = now.Hour > 12 ? "PM" : "AM";var amOrPmTextWidth = paint.MeasureText(amOrPm);var angle2 = Math.PI / 6 * (12 - 3);canvas.DrawText(amOrPm, (float)(centerPoint.X + Math.Cos(angle2) * TIPS - amOrPmTextWidth / 2), (float)(centerPoint.Y + Math.Sin(angle2) * TIPS), paint);}}
运行结果
总结
这个录的GIF播放效果真不错,基本体现出来了效果。
也算是入门了,后期,可以基于SkiaSharp,做更多的案例,出来,当然,还是基于自绘的实现。
代码地址
https://github.com/kesshei/WPFSkiaClockDemo.git
https://gitee.com/kesshei/WPFSkiaClockDemo.git
阅
一键三连呦!,感谢大佬的支持,您的支持就是我的动力!