SkiaSharp 之 WPF 自绘时钟(案例版)

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渲染器,一直没有动手,在搜集资料,现在基本搜集的差不多了,所以,就找点例子,学学,也挺有趣的。

一个时钟的效果

大概是以下的样子,也挺简单的,就是对度数是要计算的,用到的方法,也就画圆和画路径以及画文本几个方法。

10b5794d819831c57dd49ee412790fcd.png

然后,根据时间,自动转动时钟的指针。

自从毕业后,就没有做过这样的案例了。但是,上手了,感觉还是很欣喜的。

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);}}

运行结果

f75fa6646400cf29e0170c193e35398e.gif

总结

这个录的GIF播放效果真不错,基本体现出来了效果。

也算是入门了,后期,可以基于SkiaSharp,做更多的案例,出来,当然,还是基于自绘的实现。

代码地址

https://github.com/kesshei/WPFSkiaClockDemo.git

https://gitee.com/kesshei/WPFSkiaClockDemo.git

一键三连呦!,感谢大佬的支持,您的支持就是我的动力!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/284824.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

推荐一简单易用的脑图制作工具

幕布是什么&#xff1f; 大纲文档工具&#xff0c;管理你的大脑层级折叠文字&#xff0c;结构化思考助手一键转换思维导图并编辑&#xff0c;效率翻倍幕布可以做什么&#xff1f; 大纲笔记&#xff0c;思维整理 学习笔记清单工具 管理日程管理待办购物清单等等内容创作会议记录…

【QGIS入门实战精品教程】4.5:QGIS打开Excel中的点坐标,并生成矢量文件

QGIS中可以很方便添加Excel或其他文本格式的点坐标,并将其转为矢量等多种格式的文件。 扩展阅读: 【ArcGIS风暴】ArcGIS 10.2导入Excel数据X、Y坐标(经纬度、平面坐标),生成Shapefile点数据图层 文章目录 1. 数据准备2. 添加数据3. 保存文矢量文件1. 数据准备 本实验使用…

腾讯云EKS 上部署 eshopondapr

腾讯云容器服务&#xff08;Tencent Kubernetes Engine&#xff0c;TKE&#xff09;基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务。腾讯云容器服务完全兼容原生 kubernetes API &#xff0c;扩展了腾讯云的云硬盘、负载均衡等 kubernetes 插件&…

[转]一往无前 | 小米十周年,雷军公开演讲全文

2020年8月11日19:30&#xff0c;小米十周年&#xff0c;雷军公开演讲如约而至。在近3小时的演讲中&#xff0c;雷军用20个故事回顾了小米过去的热血10年&#xff0c;也展望了新的10年&#xff1a; - 创新之火将会照亮每个疯狂的想法&#xff0c;小米将成为工程师向往的圣地。 -…

JAVA单例之我见

为什么80%的码农都做不了架构师&#xff1f;>>> 单例模式作为设计模式中最简单的一种&#xff0c;是一个被说烂了的东西。但是在项目中还是会发现关于单例模式的一些错误实现&#xff0c;可见单例也并不是我们想象的那么简单。最近陆陆续续看了几篇关于单例的博客&…

「刘一哥GIS」系列专栏《QGIS入门实战精品教程(配套案例数据)》

「刘一哥GIS」系列专栏《QGIS入门实战精品教程&#xff08;配套案例数据&#xff09;》全新上线了&#xff0c;欢迎广大GISer朋友关注&#xff0c;一起探索GIS奥秘&#xff0c;分享GIS价值&#xff01; 本专栏以实战案例的形式&#xff0c;深入浅出地介绍了QGIS的基本使用方法&…

MyEclipse的Git配置

1.下载&#xff1a;git的插件egit 并解压 插件 下载地址&#xff1a;http://www.eclipse.org/egit/download/ 所有版本&#xff1a;http://wiki.eclipse.org/EGit/FAQ#Where_can_I_find_older_releases_of_EGit.3F 2.在MyEclipse安装目录下的dropins文件夹下创建egit文件夹 3.…

VSCode 插件开发实例(WebView):微信读书 ^-^边撸代码边看小说^-^

最终效果 主要代码 package.json {"name": "WeReadForVSCodeJackieZheng","repository": {"type": "git","url": "https://github.com/JackieZheng/WeReadForVSCode.git"},"displayName": &q…

【QGIS入门实战精品教程】4.7:QGIS如何将矢量数据转为GeoJSON格式?

本文以案例的形式,讲述在QGIS专业软件中,将矢量数据转为GeoJSON的方法。 扩展阅读: 【ArcGIS风暴】如何将矢量数据(点、线、面)折点坐标转为GeoJSON格式? 在QGIS中,可以直接将数据导出为GeoJSON格式。具体操作方法是:右键矢量数据图层→导出图层→到文件,如下图所示:…

Git的纯命令操作,Install,Clone , Commit,Push,Pull,版本回退,撤销更新,分支的创建/切换/更新/提交/合并,代码冲突...

Git的纯命令操作&#xff0c;Install&#xff0c;Clone , Commit&#xff0c;Push&#xff0c;Pull&#xff0c;版本回退&#xff0c;撤销更新&#xff0c;分支的创建/切换/更新/提交/合并&#xff0c;代码冲突 这篇是接着上篇分布式版本库——Windows下Git的环境部署以及在Git…

【QGIS入门实战精品教程】3.3:QGIS如何打开ArcGIS创建的文件数据库(GDB)?

在行业应用中,GIS地理空间数据往往存储在ESRI ArcGIS的文件地理数据库(File GeodataBase),因此,ArcGIS与QGIS的数据交互、共享就显得非常重要。QGIS3可以直接打开File GDB数据,并对数据进行显示、查看、处理等操作。具体的步骤如下: 相关阅读:【QGIS入门实战精品教程】3…

.NET 6 Linux 系统服务 Systemd (案例版)

.Net Core Windows 系统服务&#xff0c;之前已经写过了&#xff0c;但是&#xff0c;对于Linux的系统服务&#xff0c;却没有写过&#xff0c;主要是因为&#xff0c;大部分Linux的.Net服务都直接Docker了&#xff0c;当然&#xff0c;不排除有这种使用的&#xff0c;可能搞成…

[转]IaaS、PaaS、SaaS、CaaS、MaaS五者的区别

云计算构架图 很明显&#xff0c;这五者之间主要的区别在于第一个单词&#xff0c;而aaS都是as-a-service&#xff08;即服务&#xff09;的意思&#xff0c;这五个模式都是近年来兴起的&#xff0c;且这五者都是云计算的落地产品&#xff0c;所以我们先来了解一下云…

聊聊 C++ 中的四种类型转换符

一&#xff1a;背景 在玩 C 的时候&#xff0c;经常会用 void* 来指向一段内存地址开端&#xff0c;然后再将其强转成尺度更小的 char* 或 int* 来丈量一段内存&#xff0c;参考如下代码&#xff1a;int main() {void* ptr malloc(sizeof(int) * 10);int* int_ptr (int*)ptr;…

【QGIS入门实战精品教程】3.1:QGIS如何连接SQL Server数据库?

文章目录 软件必备测试SQL Server服务是否启动QGIS与SQL Server建立连接软件必备 SQL Server 2008 R2QGIS 3.22.3测试SQL Server服务是否启动 打开SQL Server配置管理器,查看MSSQLSERVER服务的启动情况。

开源重量级的流程引擎或UI引擎

关注这两个方面的同学个踊跃加粉了~~同时在下面回复期望开源哪一个&#xff0c;将先开源呼声高的一个。 好吧&#xff0c;先小秀一下UI&#xff1a; 增加下面的pom依赖&#xff0c;表示此工程需要org.tinygroup.aerowindow ?12345<dependency> <groupId>org.tinyg…

阿里云网盘内测开启 填写申请表获取邀请码 附最新申请地址

日前有相关报道显示&#xff0c;阿里方面推出了一款名为“阿里云网盘”的独立App&#xff0c;并且其是由阿里云团队开发&#xff0c;定位则是为C端用户提供可靠安全的存储备份及智能相册等功能。据了解&#xff0c;目前这款APP尚未正式上线&#xff0c;暂时还在邀请制测试阶段。…

跟我做⼀个⾼德地图的 iOS / Android MAUI控件(Android 原⽣库绑定)

我们已经介绍了如何通过 .NET 绑定 iOS 原⽣库 &#xff0c;本篇开始介绍⼀下如何通过 .NET 绑定 Android 原⽣库。Android的库Android 的库以 .jar 做打包&#xff0c; 通过⼯具你可以将多个 .jar 完成绑定&#xff0c;然后通过 C# 调⽤原⽣的 Java 库。对⽐起 iOS &#xff0…

【QGIS入门实战精品教程】4.6:QGIS实现栅格(影像、DEM)的拼接与掩膜提取

参考阅读:ArcGIS实验教程——实验十一:影像拼接与提取 加载实验数据 本实验所采用的栅格数据为两个dem数据和一个矢量范围数据,加载如下图所示: 栅格数据信息如下: 栅格拼接 点击下拉菜单【栅格】→【杂项】→【合并(merge)】,如下所示:

ReSharper 2020.2 补丁

ReSharper 是一个JetBrains公司出品的著名的代码生成工具。其能帮助Microsoft Visual Studio成为一个更佳的IDE&#xff0c;它包括一系列丰富的能大大增加C#和Visual Basic .net开发者生产力的特征。使用ReSharper&#xff0c;你可以进行深度代码分析&#xff0c;智能代码协助…