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;思维整理 学习笔记清单工具 管理日程管理待办购物清单等等内容创作会议记录…

自动性能统计信息(三)(Automatic Performance Statistics)

1.3 管理自动工作负载库&#xff08;AWR&#xff09;本节讲述如何管理AWR&#xff0c;包含以下主题&#xff1a; 管理快照 管理基线 管理基线模板 传输自动工作负载库数据 使用自动工作负载库视图 生成AWR报告 生成AWR对比报告 生成ASH报告 …

su: user tomcat does not exist

http://www.cnblogs.com/allegro/p/5005352.html 问题在于 你的startup.sh 里面设置了 用户,你需要修改为root或者tomcat用户 这是开发 迁移碰到的问题 test ".$TOMCAT_USER" . && TOMCAT_USERtomcat # Set JAVA_HOME to working JDK or JRE # JAVA_HOME/op…

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

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

[NOI2014]起床困难综合症

从高位往地位贪心即可 # include <bits/stdc.h> # define IL inline # define RG register # define Fill(a, b) memset(a, b, sizeof(a)) using namespace std; typedef long long ll; const int _(1e5 10);IL ll Read(){RG char c getchar(); RG ll x 0, z 1;for(;…

腾讯云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.…

ASP.NET Core 定时刷新第三方 Token

前言在《ASP.NET Core 自动刷新JWT Token》中我们实现了为客户端自动提供最新的Token。但是&#xff0c;当我们的 ASP.NET Core 应用需要调用第三方 API 时&#xff0c;如何更优雅地刷新第三方提供的 Token 呢&#xff1f;思路我们可以在启动时就获取第三方提供的 Token 并保存…

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…

掌握jQuery插件开发

在实际开发工作中&#xff0c;总会碰到像滚动&#xff0c;分页&#xff0c;日历等展示效果的业务需求&#xff0c;对于接触过jQuery以及熟悉jQuery使用的人来说&#xff0c;首先想到的肯定是寻找现有的jQuery插件来满足相应的展示需求。目前页面中常用的一些组件&#xff0c;都…

List 分页加载数据控制机制

分页加载是一种应用很广泛的数据展示控制机制&#xff0c;相信绝大多数开发者对于这一套机制都非常熟悉。这篇文章的主要目的结合实际的使用场景&#xff0c;对以往在开发中遇到一些概念进行梳理&#xff0c;归纳的同时加深理解&#xff0c;也希望能帮助更多刚刚接触到开发的同…

【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;可能搞成…

封装一个Array 数据 绑定 html select 方法

/** * * param {} select select控件 * param {} nodes Array数据 * param {} value value绑定项 * param {} text text绑定项 * param {} prompt 选择提示信息 * returns {} */ function bindSelect(select, nodes, value, text, prompt) {select.empty();if (prom…

XmlParser和HtmlParser

经常要用的Xml和Html解决&#xff0c;实际上这个领域也有非常好的解决方案。 相对来说现在各种开源的Xml解析功能比较丰富&#xff0c;机制也比较灵活&#xff0c;但是由于他功能比较完善&#xff0c;干的事情比较多&#xff0c;所以性能方面也慢一点&#xff1b;另外&#xff…