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 模拟抖音很火的罗盘时钟,附源码,下载就能跑的更多相关文章

  1. Web 开发中很实用的10个效果【附源码下载】

    在工作中,我们可能会用到各种交互效果.而这些效果在平常翻看文章的时候碰到很多,但是一时半会又想不起来在哪,所以养成知识整理的习惯是很有必要的.这篇文章给大家推荐10个在 Web 开发中很有用的效果,记 ...

  2. 分享一组很赞的 jQuery 特效【附源码下载】

    作为最优秀的 JavaScript 库之一,jQuery 不仅使用简单灵活,同时还有许多成熟的插件可供选择,它可以帮助你在项目中加入漂亮的效果.这篇文章挑选了8个优秀的 jQuery 实例教程,这些  ...

  3. 转:Web 开发中很实用的10个效果【附源码下载】

    原文地址:http://www.cnblogs.com/lhb25/p/10-useful-web-effect.html 在工作中,我们可能会用到各种交互效果.而这些效果在平常翻看文章的时候碰到很多 ...

  4. 抖音很火的存钱计划,让python告诉你总共可以存到多少钱!

    抖音上有个很火的存钱计划,说是第一天存1块钱,第二天存2块钱,第三天存3块钱.....依此类推存365天,总共可以存到多少钱,我们现在用python告诉你怎么做: #定个初始存入金额 money = ...

  5. WPF一步步实现完全无边框自定义Window(附源码)

    在我们设计一个软件的时候,有很多时候我们需要按照美工的设计来重新设计整个版面,这当然包括主窗体,因为WPF为我们提供了强大的模板的特性,这就为我们自定义各种空间提供了可能性,这篇博客主要用来介绍如何自 ...

  6. Android 音视频深入 十五 FFmpeg 推流mp4文件(附源码下载)

    源码地址https://github.com/979451341/Rtmp 1.配置RTMP服务器 这个我不多说贴两个博客分别是在mac和windows环境上的,大家跟着弄 MAC搭建RTMP服务器h ...

  7. Android 音视频深入 四 录视频MP4(附源码下载)

    本篇项目地址,名字是<录音视频(有的播放器不能放,而且没有时长显示)>,求star https://github.com/979451341/Audio-and-video-learnin ...

  8. Android 音视频深入 十九 使用ijkplayer做个视频播放器(附源码下载)

    项目地址https://github.com/979451341/Myijkplayer 前段时候我觉得FFmpeg做个视频播放器好难,虽然播放上没问题,但暂停还有通过拖动进度条来设置播放进度,这些都 ...

  9. Android 音视频深入 十六 FFmpeg 推流手机摄像头,实现直播 (附源码下载)

    源码地址https://github.com/979451341/RtmpCamera/tree/master 配置RMTP服务器,虽然之前说了,这里就直接粘贴过来吧 1.配置RTMP服务器 这个我不 ...

随机推荐

  1. 对于web前端的理解

    对于web前端的理解 其实写这篇文章的首要目的是为了准备一道面试题——你对前端的看法是什么?本文不会仅从技术角度去考虑这个问题,还会依据这个社会的变革去讨论这个问题.本文仅代表个人观点,不喜勿喷. W ...

  2. 【开发者portal在线开发插件系列四】数组 及 可变长度数组

    基础篇 基础场景见上面两个帖子,这里单独说明数组和可变长度数组的用法. 话不多说,开始今天的演(表)示(演) Profile和插件开发 添加一个string类型的属性: 在插件里添加一条数据上报消息: ...

  3. Android多线程之(一)——View.post()篇

    前言 提起View.post(),相信不少童鞋一点都不陌生,它用得最多的有两个功能,使用简便而且实用: 1)在子线程中更新UI.从子线程中切换到主线程更新UI,不需要额外new一个Handler实例来 ...

  4. eclipse m2eclipse 从Maven的本地库中读取依赖库

    在Mac pro的终端中执行命令 mvn package 后,已经把该工程所需要的依赖库(dependancies)下载到本地库,但在把该工程 import 到 eclipse中时,发现m2eclip ...

  5. 产品vs程序员:你知道www是怎么来的吗?

    精彩回顾: 我是一个explorer的线程 我是一个杀毒软件线程 我是一个IE浏览器线程 比特宇宙-TCP/IP的诞生 Unix.Linux.Windows三大帝国集团发表<关于比特宇宙推进经贸 ...

  6. ACM-ICPC 2018 焦作赛区网络预赛 H题 String and Times(SAM)

    Now you have a string consists of uppercase letters, two integers AA and BB. We call a substring won ...

  7. promise 进阶 —— async / await 结合 bluebird

    一.背景 1.Node.js 异步控制 在之前写的 callback vs async.js vs promise vs async / await 里,我介绍了 ES6 的 promise 和 ES ...

  8. MDS 多活配置

    CephFS 介绍及使用经验分享 阅读 1179 收藏 2 2019-01-14 原文链接:www.jianshu.com WebRTC SFU中发送数据包的丢失反馈juejin.im 目录 Ceph ...

  9. nessus安装、msfconsole辅助模块使用(网安全实训第三天)

    本期内容:nessus安装.msfconsole辅助模块使用.后渗透攻击 1. nessus安装 2.msfconsole辅助模块使用 3.后渗透攻击 1. nessus安装 (1)下载nessus ...

  10. 解密国内BAT等大厂前端技术体系-携程篇(长文建议收藏)

    1 引言 为了了解当前前端的发展趋势,让我们从国内各大互联网大厂开始,了解他们的最新动态和未来规划.这是解密大厂前端技术体系的第四篇,前三篇已经讲述了阿里.腾讯.百度在前端技术这几年的技术发展. 这一 ...