一、运行效果图
源代码链接https://download.csdn.net/download/afu1972715000/11966103
二、xaml
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfClock"
mc:Ignorable="d"
Title="WindowClock" Height="600" Width="1280" WindowStartupLocation="CenterScreen">
三、代码
namespace WpfClock
{
///
/// WindowClock.xaml 的交互逻辑
///
public partial class WindowClock : Window
{
// 共用字段
DispatcherTimer timer = new DispatcherTimer(); // 计时器
DateTime CurrTime = DateTime.Now; // 当前时间
// 模拟时钟字段定义
double radius = 250; // 圆半径
double angle = 360; // 角度
Point Opos = new Point(); // 原点位置
Line HourLine, MinuLine, SecdLine; // 时针、分针、秒针
Label numberClock = new Label();
//计时器
System.Timers.Timer timer2 = new System.Timers.Timer(1000);
public WindowClock()
{
InitializeComponent();
// 原点位置
Opos = new Point(250, 250);
// 初始化计时器
timer.Interval = TimeSpan.FromMilliseconds(100);
timer.Tick += Timer_Tick;
timer.IsEnabled = true;
timer.Start();
// 初始化时钟针
HourLine = new Line();
MinuLine = new Line();
SecdLine = new Line();
DrawCircle();
DrawDigit();
DrawGridLine();
DrawOCircle();
DrawNumerClock();
#region 初始化时间
secondPointer.Angle = DateTime.Now.Second * 6;
minutePointer.Angle = DateTime.Now.Minute * 6;
hourPointer.Angle = (DateTime.Now.Hour * 30) + (DateTime.Now.Minute * 0.5);
this.labTime.Content = DateTime.Now.ToString("HH:mm:ss");
#endregion
timer2.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
timer2.Enabled = true;
}
private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
//UI异步更新
this.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() =>
{
//秒针转动,秒针绕一圈360度,共60秒,所以1秒转动6度
secondPointer.Angle = DateTime.Now.Second * 6;
//分针转动,分针绕一圈360度,共60分,所以1分转动6度
minutePointer.Angle = DateTime.Now.Minute * 6;
//时针转动,时针绕一圈360度,共12时,所以1时转动30度。
//另外同一个小时内,随着分钟数的变化(绕一圈60分钟),时针也在缓慢变化(转动30度,30/60=0.5)
hourPointer.Angle = (DateTime.Now.Hour * 30) + (DateTime.Now.Minute * 0.5);
//更新时间值
this.labTime.Content = DateTime.Now.ToString("HH:mm:ss");
//更新时间值
//this.labTime2.Content = DateTime.Now.ToString("HH:mm:ss");
}));
}
///
/// 画表盘外圆
///
private void DrawCircle()
{
Ellipse ellipse = new Ellipse();
ellipse.Stroke = Brushes.DarkGray;
ellipse.StrokeThickness = 4;
ellipse.Width = 500;
ellipse.Height = 500;
ellipse.Fill = Brushes.Gray;
Canvas.SetLeft(ellipse, 0);
Canvas.SetTop(ellipse, 0);
AnalogCanvs.Children.Add(ellipse);
Ellipse ellipse1 = new Ellipse();
ellipse1.Stroke = Brushes.Gray;
ellipse1.StrokeThickness = 2;
ellipse1.Width = 510;
ellipse1.Height = 510;
Canvas.SetLeft(ellipse1, -5);
Canvas.SetTop(ellipse1, -5);
AnalogCanvs.Children.Add(ellipse1);
}
///
///画数字时钟
///
private void DrawNumerClock()
{
//< Label Content = "08:08:08" FontSize = "16" Foreground = "Black" Height = "Auto" HorizontalAlignment = "Center"
// Name = "labTime2" VerticalAlignment = "Bottom" Width = "Auto" Canvas.Left = "201" Canvas.Top = "320" />
//Label numberClock = new Label();
numberClock.Name = "labTime2";
numberClock.Content = "08:08:08";
numberClock.FontSize = 16;
numberClock.Foreground = new SolidColorBrush(Colors.White); //用固态画刷填充前景色
Canvas.SetLeft(numberClock, 220);
Canvas.SetTop(numberClock, 320);
AnalogCanvs.Children.Add(numberClock);
}
///
/// 圆形表心圆
///
private void DrawOCircle()
{
Ellipse ellipseO = new Ellipse();
ellipseO.Width = 30;
ellipseO.Height = 30;
ellipseO.Fill = Brushes.Blue;
Canvas.SetLeft(ellipseO, Opos.X - 15);
Canvas.SetTop(ellipseO, Opos.Y - 15);
if (AnalogCanvs.Children.Contains(ellipseO))
AnalogCanvs.Children.Remove(ellipseO);
AnalogCanvs.Children.Add(ellipseO);
}
///
/// 画圆表盘数字
///
private void DrawDigit()
{
double x, y;
for (int i = 1; i < 13; i++)
{
angle = WrapAngle(i * 360.0 / 12.0) - 90.0;
angle = ConvertDegreesToRadians(angle);
x = Opos.X + Math.Cos(angle) * (radius - 36) - 8;
y = Opos.Y + Math.Sin(angle) * (radius - 36) - 15;
TextBlock digit = new TextBlock();
digit.FontSize = 26;
digit.Text = i.ToString();
// 数字12位置校正
if (i == 12)
{
Canvas.SetLeft(digit, x - 8);
}
else
{
Canvas.SetLeft(digit, x);
}
Canvas.SetTop(digit, y);
AnalogCanvs.Children.Add(digit);
}
}
///
/// 画圆表刻度
///
private void DrawGridLine()
{
double x1 = 0, y1 = 0;
double x2 = 0, y2 = 0;
for (int i = 0; i < 60; i++)
{
double angle1 = WrapAngle(i * 360.0 / 60.0) - 90;
angle1 = ConvertDegreesToRadians(angle1);
if (i % 5 == 0)
{
x1 = Math.Cos(angle1) * (radius - 20);
y1 = Math.Sin(angle1) * (radius - 20);
}
else
{
x1 = Math.Cos(angle1) * (radius - 10);
y1 = Math.Sin(angle1) * (radius - 10);
}
x2 = Math.Cos(angle1) * (radius - 5);
y2 = Math.Sin(angle1) * (radius - 5);
Line line = new Line();
line.X1 = x1;
line.Y1 = y1;
line.X2 = x2;
line.Y2 = y2;
line.Stroke = Brushes.Black;
line.StrokeThickness = 3;
Canvas.SetLeft(line, Opos.X);
Canvas.SetTop(line, Opos.Y);
AnalogCanvs.Children.Add(line);
}
}
///
/// 画时针
///
private void DrawHourLine()
{
int hour = CurrTime.Hour;
int minu = CurrTime.Minute;
double dminu = minu / 60.0; // 根据分钟数增加时针偏移
double dhour = hour + dminu;
double hour_angle = WrapAngle(dhour * (360.0 / 12.0) - 90.0);
hour_angle = ConvertDegreesToRadians(hour_angle);
double x = Math.Cos(hour_angle) * (radius - 100);
double y = Math.Sin(hour_angle) * (radius - 100);
HourLine.X1 = 0;
HourLine.Y1 = 0;
HourLine.X2 = x;
HourLine.Y2 = y;
HourLine.Stroke = Brushes.Black;
HourLine.StrokeThickness = 4;
Canvas.SetLeft(HourLine, Opos.X);
Canvas.SetTop(HourLine, Opos.Y);
if (AnalogCanvs.Children.Contains(HourLine))
{
AnalogCanvs.Children.Remove(HourLine);
}
AnalogCanvs.Children.Add(HourLine);
}
///
/// 画分针
///
private void DrawMinuteLine()
{
int minu = CurrTime.Minute;
int sec = CurrTime.Second;
double dsec = sec / 60.0; // 根据秒数增加时针偏移
double dminu = minu + dsec;
double minu_angle = WrapAngle(dminu * (360.0 / 60.0) - 90);
minu_angle = ConvertDegreesToRadians(minu_angle);
double x = Math.Cos(minu_angle) * (radius - 50);
double y = Math.Sin(minu_angle) * (radius - 50);
MinuLine.X1 = 0;
MinuLine.Y1 = 0;
MinuLine.X2 = x;
MinuLine.Y2 = y;
MinuLine.Stroke = Brushes.Yellow;
MinuLine.StrokeThickness = 4;
Canvas.SetLeft(MinuLine, Opos.X);
Canvas.SetTop(MinuLine, Opos.Y);
if (AnalogCanvs.Children.Contains(MinuLine))
{
AnalogCanvs.Children.Remove(MinuLine);
}
AnalogCanvs.Children.Add(MinuLine);
}
///
/// 画秒针
///
private void DrawSecondLine()
{
int second = CurrTime.Second;
// 秒针正方向点
double se_angle = WrapAngle(second * (360.0 / 60.0) - 90);
se_angle = ConvertDegreesToRadians(se_angle);
double sec_x = Math.Cos(se_angle) * (radius - 40);
double sec_y = Math.Sin(se_angle) * (radius - 40);
// 秒针反方向点
se_angle = WrapAngle(second * (360.0 / 60.0) + 90);
se_angle = ConvertDegreesToRadians(se_angle);
double sec_x_ = Math.Cos(se_angle) * (radius - 180);
double sec_y_ = Math.Sin(se_angle) * (radius - 180);
SecdLine.X1 = sec_x_;
SecdLine.Y1 = sec_y_;
SecdLine.X2 = sec_x;
SecdLine.Y2 = sec_y;
SecdLine.Stroke = Brushes.Red;
SecdLine.StrokeThickness = 3;
Canvas.SetLeft(SecdLine, Opos.X);
Canvas.SetTop(SecdLine, Opos.Y);
if (AnalogCanvs.Children.Contains(SecdLine))
{
AnalogCanvs.Children.Remove(SecdLine);
}
AnalogCanvs.Children.Add(SecdLine);
}
///
/// 角度360度进制
///
///
///
private double WrapAngle(double angle)
{
return angle % 360;
}
///
/// 将角度转为弧度
///
///
///
private double ConvertDegreesToRadians(double degrees)
{
double radians = (Math.PI / 180) * degrees;
return radians;
}
///
/// 更新小时针、分针、秒针
///
private void Update()
{
DrawHourLine();
DrawMinuteLine();
DrawSecondLine();
//DrawOCircle();
//DrawNumerClock();
numberClock.Content = DateTime.Now.ToString("HH:mm:ss");
}
///
/// 计时器事件
///
///
///
private void Timer_Tick(object sender, EventArgs e)
{
// 更新当前时间
CurrTime = DateTime.Now;
// 更新圆盘时针
Update();
}
}
}