1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > wpf 模拟抖音很火的罗盘时钟 附源码 解压就能跑

wpf 模拟抖音很火的罗盘时钟 附源码 解压就能跑

时间:2024-02-29 00:47:17

相关推荐

wpf 模拟抖音很火的罗盘时钟 附源码 解压就能跑

wpf 模拟抖音很火的罗盘时钟,附源码,解压就能跑

前端时间突然发现,抖音火了个壁纸,就是黑底蕾丝~~~ 错错错,黑底白字的罗盘时钟!

作为程序员的我,也觉得很新颖,所以想空了研究下,这不,空下来了就用wpf,写个属于.net自己的罗盘时钟,目前只实现了时分秒,农历日期等逻辑都是一样的,所以就略了,有兴趣的朋友,可以继续深入!

最开始想直接弄成成exe,方便拷贝,到处运行使用的,但是考虑到,万一有网友朋友们需要,所以我还是把封成一个dll,需要的地方添加引用即可!

为了弄这个,还恶补了下,高中还是初中的知识,sin30,cos60,呵呵,正弦,余弦,所以不明白的朋友们需要先了解清楚这个,因为罗盘是旋转,需要用到计算这个值!

不废话了,先上图看下效果!

ok,整体效果就是这样了,中间是鄙人的名称缩写,抖音上是很潦草的,我就随便啦,占个位置,不然显得很空洞!

下面说说代码

主要是,RomeClockControlLibrary,这个是对控件的封装,上面那个启动程序只是一个容器,或者说是调用者,当然,如果要达到我这个效果,实现圆形的窗口透明的朋友们,可以看下借鉴!

<UserControl x:Class="RomeClockControlLibrary.RomeClockControl"xmlns="/winfx//xaml/presentation"xmlns:x="/winfx//xaml"xmlns:mc="/markup-compatibility/" xmlns:d="/expression/blend/" xmlns:local="clr-namespace:RomeClockControlLibrary"mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"><Border x:Name="bor"Background="#000000"><Grid x:Name="grid" ></Grid></Border></UserControl>

上面是前端代码,有点基础的都应该看得懂,没什么可说的

using System;using System.Collections.Generic;using System.Diagnostics;using System.Linq;using System.Text;using System.Threading;using System.Threading.Tasks;using System.Windows;using System.Windows.Controls;using System.Windows.Data;using System.Windows.Documents;using System.Windows.Input;using System.Windows.Media;using System.Windows.Media.Animation;using System.Windows.Media.Imaging;using System.Windows.Navigation;using System.Windows.Shapes;namespace RomeClockControlLibrary{/// <summary>/// 罗马时钟/// </summary>public partial class RomeClockControl : UserControl, IDisposable{public RomeClockControl(){InitializeComponent();}/// <summary>/// x轴的中心位置/// </summary>private double CenterPixToX => this.ActualWidth / 2;/// <summary>/// y轴的中心位置/// </summary>private double CenterPixToY => this.ActualHeight / 2;/// <summary>/// 秒/// </summary>private Canvas CanvasHour = null;/// <summary>/// 分/// </summary>private Canvas CanvasMinute = null;/// <summary>/// 时/// </summary>private Canvas CanvasSecond = null;/// <summary>/// UI更新线程/// </summary>private Thread thread = null;/// <summary>/// 缓存时的显示控件/// </summary>private TextBlock BlockHour = null;/// <summary>/// 缓存分的显示控件/// </summary>private TextBlock BlockMinute = null;/// <summary>/// 缓存秒的显示控件/// </summary>private TextBlock BlockSecond = null;/// <summary>/// 添加控件/// </summary>private void Add(AddType type){var offset = 0;//偏移量var count = 0;//总量var str = string.Empty;var time = 0;double AngleTime = 0;Canvas canvas = new Canvas();canvas.Tag = type;switch (type){case AddType.Hour:offset = 95;count = 24;str = "时";CanvasHour = canvas;time = DateTime.Now.Hour;break;case AddType.Minute:offset = 60;count = 60;str = "分";CanvasMinute = canvas;time = DateTime.Now.Minute;break;case AddType.Second:offset = 30;count = 60;str = "秒";CanvasSecond = canvas;time = DateTime.Now.Second;break;default:return;}var angle = 360 / count;//角度var x = CenterPixToX - offset;//起始位置var y = CenterPixToY - offset;for (int i = 0; i < count; i++){TextBlock t = new TextBlock();if (i <= 9){t.Text = $"0{i}{str}";}else{t.Text = $"{i}{str}";}t.Tag = i;t.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#7d7d7d"));canvas.Children.Add(t);var sinv = Math.Sin((90 - angle * i) * (Math.PI / 180));var cosv = Math.Cos((90 - angle * i) * (Math.PI / 180));var a = CenterPixToY - y * sinv;var b = CenterPixToX + y * cosv;Canvas.SetLeft(t, b);Canvas.SetTop(t, a);//设置角度RotateTransform r = new RotateTransform();r.Angle = angle * i - 90;t.RenderTransform = r;if (i == time){AngleTime = 360 - r.Angle;//更新样式t.Foreground = new SolidColorBrush(Colors.White);switch (type){case AddType.Hour:BlockHour = t;break;case AddType.Minute:BlockMinute = t;break;case AddType.Second:BlockSecond = t;break;}}}grid.Children.Add(canvas);//获取当前时间,旋转对应的角度RotateTransform rtf = new RotateTransform();rtf.CenterX = CenterPixToX;rtf.CenterY = CenterPixToY;rtf.Angle = AngleTime;canvas.RenderTransform = rtf;}/// <summary>/// 渲染时钟/// </summary>public void Show(){Dispose();//设置圆角bor.CornerRadius = new CornerRadius(this.ActualWidth / 2);Add(AddType.Hour);Add(AddType.Minute);Add(AddType.Second);AddName();thread = new Thread(new ThreadStart(threadMethod));thread.IsBackground = true;thread.Start();}/// <summary>/// 生成名称/// </summary>private void AddName(){TextBlock tb = new TextBlock();tb.Text = "XL";tb.Foreground = new SolidColorBrush(Colors.White);tb.FontSize = 60;tb.FontFamily = new FontFamily("华文琥珀");tb.HorizontalAlignment = HorizontalAlignment.Center;tb.VerticalAlignment = VerticalAlignment.Center;grid.Children.Add(tb);}/// <summary>/// UI更新线程/// </summary>private void threadMethod(){while (true){Dispatcher.Invoke(() =>{var s = DateTime.Now.Second;var m = DateTime.Now.Minute;var h = DateTime.Now.Hour;//处理时if (m == 0 && (int)BlockHour.Tag != h){SetUI(CanvasHour, h);}//处理分if (s == 0 && (int)BlockMinute.Tag != m){SetUI(CanvasMinute, m);}//处理秒SetUI(CanvasSecond, s);});Thread.Sleep(1000);}}/// <summary>/// 更新UI/// </summary>/// <param name="can"></param>/// <param name="tag"></param>/// <param name="color"></param>private void SetUI(Canvas can, int tag){var type = (AddType)can.Tag;foreach (TextBlock item in can.Children){if ((int)item.Tag == tag){Debug.WriteLine(item.Text);var fr = item.RenderTransform as RotateTransform;var angle = 360 - fr.Angle;var rtf = can.RenderTransform as RotateTransform;DoubleAnimation db = null;if (type == AddType.Minute){angle -= 360;db = new DoubleAnimation(angle, new Duration(TimeSpan.FromSeconds(1)));pleted += DbMinute_Completed;BlockMinute = item;}else if (type == AddType.Hour){angle += 360;db = new DoubleAnimation(angle, new Duration(TimeSpan.FromSeconds(1.5)));pleted += DbHour_Completed;BlockHour = item;}else{db = new DoubleAnimation(angle, new Duration(TimeSpan.FromSeconds(0.25)));pleted += DbSecond_Completed;BlockSecond = item;}rtf.BeginAnimation(RotateTransform.AngleProperty, db);}else{item.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#7d7d7d"));}}}/// <summary>/// 秒 动画完成时/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void DbSecond_Completed(object sender, EventArgs e){BlockSecond.Foreground = new SolidColorBrush(Colors.White);}/// <summary>/// 时 动画完成时/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void DbHour_Completed(object sender, EventArgs e){var fr = CanvasHour.RenderTransform as RotateTransform;var angle = fr.Angle - 360;fr = null;RotateTransform rtf = new RotateTransform();rtf.CenterX = CenterPixToX;rtf.CenterY = CenterPixToY;rtf.Angle = angle;CanvasHour.RenderTransform = rtf;Debug.WriteLine(rtf.Angle);BlockHour.Foreground = new SolidColorBrush(Colors.White);}/// <summary>/// 分 动画完成时/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void DbMinute_Completed(object sender, EventArgs e){var fr = CanvasMinute.RenderTransform as RotateTransform;var angle = fr.Angle + 360;fr = null;RotateTransform rtf = new RotateTransform();rtf.CenterX = CenterPixToX;rtf.CenterY = CenterPixToY;rtf.Angle = angle;CanvasMinute.RenderTransform = rtf;Debug.WriteLine(rtf.Angle);BlockMinute.Foreground = new SolidColorBrush(Colors.White);}/// <summary>/// 释放/// </summary>public void Dispose(){thread?.Abort();grid.Children.Clear();}}/// <summary>/// 添加类型/// </summary>public enum AddType{Hour,Minute,Second}}

上面是后端逻辑,这才是重点,调用者通过show,调用显示的;在show里面会开启一个后台处理线程,来实现获取当前时间,并计算需要旋转的角度,最后采用动画更新到UI!

整个流程就是这样,有疑问的朋友,欢迎留言!

下载地址,附源码 ==》点我前往

支持原创,转载请标明出处,谢谢!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。