wpf 模拟抖音很火的罗盘时钟,附源码,解压就能跑
wpf 模擬抖音很火的羅盤時鐘,附源碼,解壓就能跑
? ? ? ?前端時間突然發現,抖音火了個壁紙,就是黑底蕾絲~~~? 錯錯錯,黑底白字的羅盤時鐘!
作為程序員的我,也覺得很新穎,所以想空了研究下,這不,空下來了就用wpf,寫個屬于.net自己的羅盤時鐘,目前只實現了時分秒,農歷日期等邏輯都是一樣的,所以就略了,有興趣的朋友,可以繼續深入!
最開始想直接弄成成exe,方便拷貝,到處運行使用的,但是考慮到,萬一有網友朋友們需要,所以我還是把封成一個dll,需要的地方添加引用即可!
為了弄這個,還惡補了下,高中還是初中的知識,sin30,cos60,呵呵,正弦,余弦,所以不明白的朋友們需要先了解清楚這個,因為羅盤是旋轉,需要用到計算這個值!
不廢話了,先上圖看下效果!
? ? ? ?ok,整體效果就是這樣了,中間是鄙人的名稱縮寫,抖音上是很潦草的,我就隨便啦,占個位置,不然顯得很空洞!
下面說說代碼
??
? ?主要是,RomeClockControlLibrary,這個是對控件的封裝,上面那個啟動程序只是一個容器,或者說是調用者,當然,如果要達到我這個效果,實現圓形的窗口透明的朋友們,可以看下借鑒!
<UserControl x:Class="RomeClockControlLibrary.RomeClockControl"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 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)));db.Completed += DbMinute_Completed;BlockMinute = item;}else if (type == AddType.Hour){angle += 360;db = new DoubleAnimation(angle, new Duration(TimeSpan.FromSeconds(1.5)));db.Completed += DbHour_Completed;BlockHour = item;}else{db = new DoubleAnimation(angle, new Duration(TimeSpan.FromSeconds(0.25)));db.Completed += 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!
整個流程就是這樣,有疑問的朋友,歡迎留言!
下載地址,附源碼 ==》?點我前往
支持原創,轉載請標明出處,謝謝!
?
總結
以上是生活随笔為你收集整理的wpf 模拟抖音很火的罗盘时钟,附源码,解压就能跑的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: go xorm 最简操作
- 下一篇: CAD 电气版 元件包含中文的描述显示问