MainWindow.xamlでアナログ時計を滑らかに


C#でアナログ時計を作ってみた

だいたい9時6分33秒くらい?かな
秒針がとても滑らかに動きます
そんな超単純なアニメーションでxamlの実力を知りました

早速、xamlコードは以下のようになりました。

MainWindow.xaml
<Window x:Class="MainWindow.AnalogClock"
        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"
        mc:Ignorable="d"
        Title="アプリケーション課題3:Analog Clock" Height="500" Width="500" 
        Loaded="Window_Loaded" >
    <Window.Resources>
        <Storyboard x:Key="SecondHand" x:Name="SecondHand" RepeatBehavior="Forever" >
            <DoubleAnimation
                Duration="0:1:0" From="0" To="360"
                Storyboard.TargetName="SecondLine"
                Storyboard.TargetProperty="(Line.RenderTransform).(RotateTransform.Angle)"
            />
        </Storyboard>
        <Storyboard x:Key="MinuteHand" x:Name="MinuteHand" RepeatBehavior="Forever">
            <DoubleAnimation
                Duration="1:0:0" From="0" To="360"
                Storyboard.TargetName="MinuteLine"
                Storyboard.TargetProperty="(Line.RenderTransform).(RotateTransform.Angle)"
            />
        </Storyboard>
        <Storyboard x:Key="HourHand" x:Name="HourHand" RepeatBehavior="Forever">
            <DoubleAnimation
                Duration="12:0:0" From="0" To="360"
                Storyboard.TargetName="HourLine"
                Storyboard.TargetProperty="(Line.RenderTransform).(RotateTransform.Angle)"
            />
        </Storyboard>
    </Window.Resources>
    <Canvas Width="400" Height="400">
        <Line x:Name="HourLine"  Stroke="Black" Fill="Black" 
              X1="200" Y1="200" X2="200" Y2="80"              
               StrokeThickness="3" >
            <Line.RenderTransform>
                <RotateTransform  x:Name="AngleHour" Angle="0" 
                                  CenterX="200" CenterY="200"/>
            </Line.RenderTransform>
        </Line>
        <Line x:Name="MinuteLine"  Stroke="Black" Fill="Black" 
              X1="200" Y1="200" X2="200" Y2="40"              
               StrokeThickness="2" >
            <Line.RenderTransform>
                <RotateTransform x:Name="AngleMinute"  Angle="0" 
                                 CenterX="200" CenterY="200"/>
            </Line.RenderTransform>
        </Line>
        <Line x:Name="SecondLine"  Stroke="Black" Fill="LightGray"
              X1="200" Y1="240" X2="200" Y2="30"  >
            <Line.RenderTransform>
                <RotateTransform x:Name="AngleSecond" Angle="0"  
                                 CenterX="200" CenterY="200"/>
            </Line.RenderTransform>
        </Line>
        <Ellipse Fill="Black" Width="10" Height="10" HorizontalAlignment="Center" 
                 VerticalAlignment="Center" 
                 Canvas.Top="195" Canvas.Left="195"/>
    </Canvas>
</Window>

さらにC#サイドのコードは以下の通り

MainWindows.xaml.cs
// ********************************************************
// *
// * 処理内容:滑らかなアナログ時計の動作を実現
// *
// *        MainWindow.xaml.cs :アナログ時計表示
// *
// *        2020.07.03 ProOJI
// *
// ********************************************************

using System;
using System.Windows;
using System.Windows.Media.Animation;

namespace MainWindow
{
    /// <summary>
    /// アナログ時計のクラス
    /// </summary>
    public partial class AnalogClock : Window
    {
        /// <summary>
        /// 初期設定
        /// </summary>
        public AnalogClock()
        {
            InitializeComponent();
            InitializeAngle();
        }
        /// <summary>
        /// アナログ時計のアニメーション
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            // 時間の針
            StartAnimation("HourHand", this.AngleHour.Angle);
            // 分の針
            StartAnimation("MinuteHand", this.AngleMinute.Angle);
            // 秒の針
            StartAnimation("SecondHand", this.AngleSecond.Angle);
        }
        /// <summary>
        /// 針の角度の初期設定
        /// </summary>
        /// <returns>なし</returns>
        void InitializeAngle()
        {
            DateTime dt = DateTime.Now;
            this.AngleSecond.Angle = dt.Second * 360.0 / 60.0;
            this.AngleMinute.Angle = (dt.Minute + dt.Second / 60.0) * 360.0 / 60.0;
            this.AngleHour.Angle = (dt.Hour + dt.Minute / 60.0) * 360.0 / 12;
        }

        /// <summary>
        /// 時計の針のアニメーション表示
        /// </summary>
        /// <param name="name">各針の名称</param>
        /// <param name="angle">針の角度</param>
        /// <returns>なし</returns>
        private void StartAnimation(string name, double angle)
        {
            var sb = this.Resources[name] as Storyboard;
            var da = sb.Children[0] as DoubleAnimation;
            da.From = angle;
            da.To = da.From + 360.0;
            sb.Begin();
        }
    }
}

まとめ

XAMLのみで、かなりのアニメーションを作ることができるのはすごい
以上!( ̄∀ ̄)