C# WPF 时钟动画(2/2)
模拟实现时钟效果,学习WPF动画好例子,本文承接上文 C# WPF 时钟动画(1/2)。
C# WPF 时钟动画(2/2)
内容目录
- 实现效果
- 业务场景
- 编码实现
- 本文参考
- 源码下载
1.实现效果
时钟实时展示系统本机时间

2.业务场景
模拟时钟
3.编码实现
使用 .Net Core 3.1 创建名为 “Clock” 的WPF解决方案,解决方案中需要添加时钟背景图片,图片如下:https://github.com/Abel13/Clock/blob/master/Clock/Assets/clock.png
3.1 主窗体 MainWindow.xaml
使用3个Border布局时钟的时针、分针、秒针,并给3个指针添加动画,动画说明如下:
- 时针每12个小时循环一圈(360°),每个小时旋转30°(30°*12=360°);
- 分针每60分钟循环一圈(360°),每分钟旋转6°(6°*60=360°);
- 秒针每60秒循环一圈(360°),每秒钟旋转6°(6°*60=360°),并且秒针旋转6°有个轻微的摆动动画。
<Window x:Class="Clock.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
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:Clock"
mc:Ignorable="d"
AllowsTransparency="True" WindowStyle="None" ResizeMode="NoResize"
Height="520" Width="520" WindowStartupLocation="CenterScreen" Background="{x:Null}">
<Window.Resources>
<Storyboard x:Key="sbseconds" RepeatBehavior="Forever">
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="second" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)">
<EasingDoubleKeyFrame KeyTime="0" Value="-90">
<EasingDoubleKeyFrame.EasingFunction>
<BackEase EasingMode="EaseOut" Amplitude="0.4"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:1" Value="-84">
<EasingDoubleKeyFrame.EasingFunction>
<BackEase EasingMode="EaseOut" Amplitude="0.4"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:2" Value="-78">
<EasingDoubleKeyFrame.EasingFunction>
<BackEase EasingMode="EaseOut" Amplitude="0.4"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:3" Value="-72">
<EasingDoubleKeyFrame.EasingFunction>
<BackEase EasingMode="EaseOut" Amplitude="0.4"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:4" Value="-66">
<EasingDoubleKeyFrame.EasingFunction>
<BackEase EasingMode="EaseOut" Amplitude="0.4"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:5" Value="-60">
<EasingDoubleKeyFrame.EasingFunction>
<BackEase EasingMode="EaseOut" Amplitude="0.4"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:6" Value="-54">
<EasingDoubleKeyFrame.EasingFunction>
<BackEase EasingMode="EaseOut" Amplitude="0.4"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:7" Value="-48">
<EasingDoubleKeyFrame.EasingFunction>
<BackEase EasingMode="EaseOut" Amplitude="0.4"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:8" Value="-42">
<EasingDoubleKeyFrame.EasingFunction>
<BackEase EasingMode="EaseOut" Amplitude="0.4"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:9" Value="-36">
<EasingDoubleKeyFrame.EasingFunction>
<BackEase EasingMode="EaseOut" Amplitude="0.4"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:10" Value="-30">
<EasingDoubleKeyFrame.EasingFunction>
<BackEase EasingMode="EaseOut" Amplitude="0.4"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:11" Value="-24">
<EasingDoubleKeyFrame.EasingFunction>
<BackEase EasingMode="EaseOut" Amplitude="0.4"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:12" Value="-18">
<EasingDoubleKeyFrame.EasingFunction>
<BackEase EasingMode="EaseOut" Amplitude="0.4"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:13" Value="-12">
<EasingDoubleKeyFrame.EasingFunction>
<BackEase EasingMode="EaseOut" Amplitude="0.4"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:14" Value="-6">
<EasingDoubleKeyFrame.EasingFunction>
<BackEase EasingMode="EaseOut" Amplitude="0.4"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:15" Value="0">
<EasingDoubleKeyFrame.EasingFunction>
<BackEase EasingMode="EaseOut" Amplitude="0.4"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:16" Value="6">
<EasingDoubleKeyFrame.EasingFunction>
<BackEase EasingMode="EaseOut" Amplitude="0.4"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:17" Value="12">
<EasingDoubleKeyFrame.EasingFunction>
<BackEase EasingMode="EaseOut" Amplitude="0.4"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:18" Value="18">
<EasingDoubleKeyFrame.EasingFunction>
<BackEase EasingMode="EaseOut" Amplitude="0.4"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:19" Value="24">
<EasingDoubleKeyFrame.EasingFunction>
<BackEase EasingMode="EaseOut" Amplitude="0.4"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:20" Value="30">
<EasingDoubleKeyFrame.EasingFunction>
<BackEase EasingMode="EaseOut" Amplitude="0.4"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:21" Value="36">
<EasingDoubleKeyFrame.EasingFunction>
<BackEase EasingMode="EaseOut" Amplitude="0.4"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:22" Value="42">
<EasingDoubleKeyFrame.EasingFunction>
<BackEase EasingMode="EaseOut" Amplitude="0.4"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:23" Value="48">
<EasingDoubleKeyFrame.EasingFunction>
<BackEase EasingMode="EaseOut" Amplitude="0.4"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:24" Value="54">
<EasingDoubleKeyFrame.EasingFunction>
<BackEase EasingMode="EaseOut" Amplitude="0.4"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:25" Value="60">
<EasingDoubleKeyFrame.EasingFunction>
<BackEase EasingMode="EaseOut" Amplitude="0.4"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:26" Value="66">
<EasingDoubleKeyFrame.EasingFunction>
<BackEase EasingMode="EaseOut" Amplitude="0.4"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:27" Value="72">
<EasingDoubleKeyFrame.EasingFunction>
<BackEase EasingMode="EaseOut" Amplitude="0.4"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:28" Value="78">
<EasingDoubleKeyFrame.EasingFunction>
<BackEase EasingMode="EaseOut" Amplitude="0.4"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:29" Value="84">
<EasingDoubleKeyFrame.EasingFunction>
<BackEase EasingMode="EaseOut" Amplitude="0.4"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:30" Value="90">
<EasingDoubleKeyFrame.EasingFunction>
<BackEase EasingMode="EaseOut" Amplitude="0.4"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource sbseconds}"/>
</EventTrigger>
</Window.Triggers>
<Grid>
<Border BorderThickness="10" BorderBrush="Black" CornerRadius="300" Width="520" Height="520">
<Grid Height="500" Width="500" HorizontalAlignment="Center" VerticalAlignment="Center">
<Border CornerRadius="350">
<Border.Background>
<ImageBrush ImageSource="Assets/clock.png"/>
</Border.Background>
</Border>
<Border CornerRadius="350" Background="#778889BB"/>
<Border x:Name="hour" CornerRadius="0 15 15 0" Height="10" Width="130" BorderThickness="3" BorderBrush="#FF66B01C" Margin="0,245,120,245" HorizontalAlignment="Right" RenderTransformOrigin="0,0.5">
<Border.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform Angle="-90"/>
<TranslateTransform/>
</TransformGroup>
</Border.RenderTransform>
</Border>
<Border x:Name="minute" CornerRadius="0 15 15 0" Height="5" Width="160" BorderThickness="3" BorderBrush="#FFD15209" Margin="250.5,247,0,248" HorizontalAlignment="Left" RenderTransformOrigin="0,0.5">
<Border.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform Angle="-90"/>
<TranslateTransform/>
</TransformGroup>
</Border.RenderTransform>
</Border>
<Border x:Name="second" CornerRadius="0 15 15 0" Height="3" Width="220" Background="Red" Margin="0,248,30,248" HorizontalAlignment="Right" RenderTransformOrigin="0,0.5">
<Border.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform Angle="-90"/>
<TranslateTransform/>
</TransformGroup>
</Border.RenderTransform>
</Border>
<Ellipse Fill="Black" Width="20" Height="20" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</Border>
</Grid>
</Window>
3.2 MainWindow.xaml.cs
后台代码开启三个指针动画,并设置各指针动画起始位置
using System;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media.Animation;
namespace Clock
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
int now_hours = DateTime.Now.Hour > 12 ? (DateTime.Now.Hour - 12) : DateTime.Now.Hour;
int now_minutes = DateTime.Now.Minute;
int now_seconds = DateTime.Now.Second;
Storyboard seconds = (Storyboard)second.FindResource("sbseconds");
seconds.Begin();
seconds.Seek(new TimeSpan(0, 0, 0, now_seconds, 0));
Storyboard minutes = (Storyboard)minute.FindResource("sbminutes");
minutes.Begin();
minutes.Seek(new TimeSpan(0, 0, now_minutes, now_seconds, 0));
Storyboard hours = (Storyboard)hour.FindResource("sbhours");
hours.Begin();
hours.Seek(new TimeSpan(0, now_hours, now_minutes, now_seconds, 0));
}
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
DragMove();
}
}
}
4.本文参考
Design com WPF 大神的学习视频:
1/2 - Creating a clock with Animations
2/2 - Creating a clock with Animations
5.代码下载
源码中实现了全部效果,大伙可以直接下载编译运行;建议看大神视频手敲一遍,加深学习印象;视频中使用Blend布局时钟、设置动画,类似PS(PhotoShop),设计界面很是方便的。
Github源码下载:Clock
除非注明,文章均由 Dotnet9 整理发布,欢迎转载。
转载请注明本文地址:https://dotnet9.com/6858.html
欢迎扫描下方二维码关注 Dotnet9 的微信公众号,本站会及时推送最新技术文章
C# WPF 时钟动画(2/2)的更多相关文章
- C# WPF 时钟动画(1/2)
微信公众号:Dotnet9,网站:Dotnet9,问题或建议:请网站留言, 如果对您有所帮助:欢迎赞赏. C# WPF 时钟动画(1/2) 内容目录 实现效果 业务场景 编码实现 本文参考 源码下载 ...
- WPF利用动画实现圆形进度条
原文:WPF利用动画实现圆形进度条 这是我的第一篇随笔,最近因为工作需要,开始学习WPF相关技术,自己想实现以下圆形进度条的效果,逛了园子发现基本都是很久以前的文章,实现方式一般都是GDI实现的,想到 ...
- WPF弹性模拟动画
原文:WPF弹性模拟动画 我们此次将要制作模拟物理中的弹性现象的交互动画,我们让一个小球向鼠标点击位置移动,这个移动的轨迹不是简单的位移,而是根据胡克定律计算得出的. 胡克定律:F=-kd F代表弹性 ...
- WPF控制动画开始、停止、暂停和恢复
1.闲言 好久也没更新一博客了,自己有点发懒,同时确实这几个月来也有点忙.风机监测软件,项目中,有这样一个小需求:正常风机在旋转的时候,上位机软要做一个风机的图片,让它不停地旋转,一但检测到下面风机停 ...
- 使用Canvas制作时钟动画
复习Javascript到Canvas的知识点,看到一个使用Canvas绘制的静态时钟例子,便想将其变成动态显示系统时间的时钟动画.另外再配上数字显示的时钟,一个小的时钟模块的诞生了!目前的界面还比较 ...
- 15个超强悍的CSS3圆盘时钟动画赏析
在网页上,特别是个人博客中经常会用到时钟插件,一款个性化的时钟插件不仅可以让页面显得美观,而且可以让访客看到当前的日期和时间.今天我们给大家收集了15个超强悍的圆盘时钟动画,很多都是基于CSS3,也有 ...
- Wpf(Storyboard)动画简单实例
原文:Wpf(Storyboard)动画简单实例 动画的三种变换方式 RotateTransform:旋转变换变化值:CenterX围绕转的圆心横坐标 CenterY纵坐标 Angle旋转角度(角度正 ...
- iOS中的时钟动画
iOS 动画效果非常多,我们在开发中可能会遇到很多动画特效,我们就会用到核心动画框架CoreAnimation,核心动画里面的动画效果有很多,都是在QuartzCore.framework框架里面,今 ...
- 14款超时尚的HTML5时钟动画
时钟动画在网页应用中也非常广泛,在一些个人博客中,我们经常会看到一些相当个性化的HTML5时钟动画.今天我们向大家分享了14款形态各异的超时尚HTML5时钟动画,其中有圆盘时钟.3D时钟.个性化时钟等 ...
随机推荐
- 【大白话系列】MySQL 学习总结 之 初步了解 MySQL 的架构设计
一.MySQL还是个黑盒子 我们都知道,只要我们系统引入了 MySQL 驱动和连接池,就能从数据库连接池获取一个数据库连接,然后就可以执行增删改查的操作了. 可是我们并不知道 MySQL 里面是怎么执 ...
- YUM安装软件提示[Errno 14] curl#6 - "Could not resolve host: mirrors.cloud.aliyuncs.com; 未知的错误"
报错如下: 翻译过来就是 所以问题很简单: 第一种情况:本地DNS服务错误 第二种情况:远程主机挂了 第三种情况:远程主机地址配置错误 第一种解决方法:换DNS 首先验证一下是不是本地DNS错误 从上 ...
- IntelliJ IDEA的这个接口调试工具真是太好用了!
你有一个思想,我有一个思想,我们交换后,一个人就有两个思想 If you can NOT explain it simply, you do NOT understand it well enough ...
- Windows下SVN权限配置
Windows下SVN权限配置 按照前面的教程装完1.6.1版以后,当svnadmin create D;\svn创建仓库后,应该在仓库目录下的config目录有3个文件— auth ...
- 全卷积网络FCN
全卷积网络FCN fcn是深度学习用于图像分割的鼻祖.后续的很多网络结构都是在此基础上演进而来. 图像分割即像素级别的分类. 语义分割的基本框架: 前端fcn(以及在此基础上的segnet,decon ...
- ORACLE隐式类型转换
隐式类型转换简介 通常ORACLE数据库存在显式类型转换(Explicit Datatype Conversion)和隐式类型转换(Implicit Datatype Conversion)两 ...
- [redis读书笔记] 第一部分 数据结构与对象 整数集合
typedef struct intset { // 编码方式 uint32_t encoding; // 集合包含的元素数量 uint32_t length; // 保存元素的数组 int8_t c ...
- 基于MATLAB的单级倒立摆仿真
有关代码及word文档请关注公众号“浮光倾云”,后台回复A010.02即可获取 一.单级倒立摆概述 倒立摆是处于倒置不稳定状态,人为控制使其处于动态平衡的一种摆,是一类典型的快速.多变量.非线性.强耦 ...
- 国内jenkins搭建不再龟速的方式
最新国内jenkisn搭建过程 第一步下载jenkins 点击进入清华源jenkins下载地址,我们下载的是jenkins-2.204.2.zip版本 之后解压后安装. 第二步配置管理员密码 自动弹出 ...
- Nodejs中,path.join()和path.resolve()的区别
在说path.join()和path.resolve()的区别之前,我先说下文件路径/和./和../之间的区别 /代表的是根目录: ./代表的是当前目录: ../代表的是父级目录. 然后再来说下pat ...
