• 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!

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

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

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

      

  • 相关阅读:
    字符串内部查找函数
    vs2005 编译zlib 1.2.3 小记
    ies4linux 安装
    详述IP数据包的转发流程
    看源代码
    091213
    值得你记住并受用一生的Word XP/2003快捷键
    java开源框架的源代码怎么读?
    excel中的EMBED域介绍
    如何用c语言实现CString的构造函数、析构函数和赋值函数?
  • 原文地址:https://www.cnblogs.com/xuling-297769461/p/10845590.html
Copyright © 2020-2023  润新知