WPF SkiaSharpで時計を作る

<B>
<font COLOR="blue" >
・~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~・<BR>
・時計のサンプルです。<BR>
・SkiaSharpについては <a href="https://qiita.com/inf102/items/e6cc6d8590b929f5e54e">別記事参照</A><BR>
・~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~・<BR>
</B>

中心から針を描画するのは面白くないので円を配置しています。
![TOP.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821882/eade02aa-f32c-420c-b48b-f0102906cdf2.jpeg)



```cs
// (c) inf102 2023
using SkiaSharp;
using SkiaSharp.Views.Desktop;
using System;
using System.Threading.Tasks;
using System.Windows;

namespace SkiaSharpSample {

    public partial class MainWindow : Window	{

        static int SS=0;
        static int HH=0;
        static int MM=0;

		public MainWindow()		{
			InitializeComponent();

		}

        private async  void Window_Loaded(object sender, RoutedEventArgs e) {

           while (true){

                Dispatcher.Invoke(() => { 
                    skiaCanvas2.InvalidateVisual(); 
                });
                
                await Task.Delay(1000); 
                DateTime dt = DateTime.Now;
                
                SS=dt.Second;
                MM=dt.Minute;
                HH=dt.Hour;
               
            }



        }

        void Moji (SKPaintSurfaceEventArgs args){

            var skPaint = new SKPaint() {
                FilterQuality = SKFilterQuality.High,
                IsAntialias = true
            };

            skPaint.TextSize = 15f;
            skPaint.Color = SKColors.Red;
            skPaint.Typeface = SKTypeface.FromFamilyName("LINE Seed JP_OTF");

            double x,y;
            
            x= RetX(0);
            y= RetY(0);
            args.Surface.Canvas.DrawText("12", (float)x, (float)y, skPaint);

            x = RetX(5);
            y = RetY(5);
            args.Surface.Canvas.DrawText("1", (float)x, (float)y, skPaint);

            x = RetX(10);
            y = RetY(10);
            args.Surface.Canvas.DrawText("2", (float)x, (float)y, skPaint);

            x = RetX(15);
            y = RetY(15);
            args.Surface.Canvas.DrawText("3", (float)x, (float)y, skPaint);

            x = RetX(20);
            y = RetY(20);
            args.Surface.Canvas.DrawText("4", (float)x, (float)y, skPaint);

            x = RetX(25);
            y = RetY(25);
            args.Surface.Canvas.DrawText("5", (float)x, (float)y, skPaint);

            x = RetX(30);
            y = RetY(30);
            args.Surface.Canvas.DrawText("6", (float)x, (float)y, skPaint);

            x = RetX(35);
            y = RetY(35);
            args.Surface.Canvas.DrawText("7", (float)x, (float)y, skPaint);

            x = RetX(40);
            y = RetY(40);
            args.Surface.Canvas.DrawText("8", (float)x, (float)y, skPaint);

            x = RetX(45);
            y = RetY(45);
            args.Surface.Canvas.DrawText("9", (float)x, (float)y, skPaint);

            x = RetX(50);
            y = RetY(50);
            args.Surface.Canvas.DrawText("10", (float)x, (float)y, skPaint);

            x = RetX(55);
            y = RetY(55);
            args.Surface.Canvas.DrawText("11", (float)x, (float)y, skPaint);

            args.Surface.Canvas.DrawText(HH.ToString() + ":" + MM.ToString() + ":" + SS.ToString(), 0,15, skPaint);


            ////////////////////////////////////////////////////////////////////////////
            double RetX(int RS){

                return ( (skiaCanvas2.CanvasSize.Width  /2) + 85 * Math.Sin(RS*3.14/30)-7 );
            }

            double RetY(int RS){
                return ( (skiaCanvas2.CanvasSize.Height /2) - 85 * Math.Cos(RS*3.14/30)+1 );

            }            
            ////////////////////////////////////////////////////////////////////////////


        }



		void PaintSurface(object sender, SKPaintSurfaceEventArgs args){

            SKImageInfo info = args.Info;
            SKSurface surface = args.Surface;
            SKCanvas canvas = surface.Canvas;
           
               
            // グラフ部背景色
            canvas.Clear(SKColors.WhiteSmoke);
            
            SKPaint A_LINE= new SKPaint{
	            Style =  SKPaintStyle.Stroke,
			    Color = new SKColor(0, 191, 200),
                IsAntialias=true,
                  
                StrokeWidth = 3

            };

            SKPaint B_LINE= new SKPaint{
	            Style =  SKPaintStyle.StrokeAndFill,
			    Color = new SKColor(125, 55, 55),
                //  StrokeCap = (SKStrokeCap)10,
                IsAntialias=true,
                  
                StrokeWidth = 3

            };

            Moji(args);

            canvas.DrawCircle((float)skiaCanvas2.CanvasSize.Width  /2, (float)skiaCanvas2.CanvasSize.Height /2, 100,A_LINE);
            canvas.DrawCircle((float)skiaCanvas2.CanvasSize.Width  /2, (float)skiaCanvas2.CanvasSize.Height /2, 65,A_LINE);
            canvas.DrawCircle((float)skiaCanvas2.CanvasSize.Width  /2, (float)skiaCanvas2.CanvasSize.Height /2 ,30,A_LINE);  


            double y,x;
            
            // 秒針
            x=skiaCanvas2.CanvasSize.Width  / 2+  30* Math.Sin(SS*3.14/30);
            y=skiaCanvas2.CanvasSize.Height / 2 - 30* Math.Cos(SS*3.14/30);
            canvas.DrawCircle((float)x,(float) y ,10,B_LINE);

            // 短針
            x = (skiaCanvas2.CanvasSize.Width  /2) + 65 * Math.Sin(HH * 3.14 / 6 + MM * 3.14 / 360);
            y = (skiaCanvas2.CanvasSize.Height /2) - 65 * Math.Cos(HH * 3.14 / 6 + MM * 3.14 / 360);
            canvas.DrawCircle((float)x,(float) y ,10,B_LINE);

            // 長針
            x = (skiaCanvas2.CanvasSize.Width  /2) + 100 * Math.Sin(MM * 3.14 / 30 + SS * 3.14 / 1800);
            y = (skiaCanvas2.CanvasSize.Height /2) - 100 * Math.Cos(MM * 3.14 / 30 + SS * 3.14 / 1800);
            canvas.DrawCircle((float)x,(float) y ,10,B_LINE);
     
		}
	}
}
```

・この時計は下記の通り。
![DHCP1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821882/e82dae2f-6017-c897-5ff7-01af716d0c83.jpeg)

```c#
using SkiaSharp;
using SkiaSharp.Views.Desktop;
using System;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;

namespace SkiaSharpSample {

    public partial class MainWindow : Window	{

        static int SS=0;
        static int HH=0;
        static int MM=0;

		public MainWindow()		{
			InitializeComponent();

		}

        private async  void Window_Loaded(object sender, RoutedEventArgs e) {

           while (true){

                Dispatcher.Invoke(() => { 
                    skiaCanvas2.InvalidateVisual(); 
                });
                
                await Task.Delay(1000); 
                DateTime dt = DateTime.Now;
                
                SS=dt.Second;
                MM=dt.Minute;
                HH=dt.Hour;
               
            }



        }

        void Moji (SKPaintSurfaceEventArgs args){

            var skPaint = new SKPaint() {
                FilterQuality = SKFilterQuality.High,
                IsAntialias = true
            };

            skPaint.TextSize = 15f;
            skPaint.Color = SKColors.Red;
            skPaint.Typeface = SKTypeface.FromFamilyName("LINE Seed JP_OTF");

            double x,y;
            
            x= RetX(0);
            y= RetY(0);
            args.Surface.Canvas.DrawText("12", (float)x-2, (float)y, skPaint);

            x = RetX(5);
            y = RetY(5);
            args.Surface.Canvas.DrawText("1", (float)x, (float)y, skPaint);

            x = RetX(10);
            y = RetY(10);
            args.Surface.Canvas.DrawText("2", (float)x, (float)y, skPaint);

            x = RetX(15);
            y = RetY(15);
            args.Surface.Canvas.DrawText("3", (float)x, (float)y, skPaint);

            x = RetX(20);
            y = RetY(20);
            args.Surface.Canvas.DrawText("4", (float)x, (float)y, skPaint);

            x = RetX(25);
            y = RetY(25);
            args.Surface.Canvas.DrawText("5", (float)x, (float)y, skPaint);

            x = RetX(30);
            y = RetY(30);
            args.Surface.Canvas.DrawText("6", (float)x, (float)y, skPaint);

            x = RetX(35);
            y = RetY(35);
            args.Surface.Canvas.DrawText("7", (float)x, (float)y, skPaint);

            x = RetX(40);
            y = RetY(40);
            args.Surface.Canvas.DrawText("8", (float)x, (float)y, skPaint);

            x = RetX(45);
            y = RetY(45);
            args.Surface.Canvas.DrawText("9", (float)x, (float)y, skPaint);

            x = RetX(50);
            y = RetY(50);
            args.Surface.Canvas.DrawText("10", (float)x, (float)y, skPaint);

            x = RetX(55);
            y = RetY(55);
            args.Surface.Canvas.DrawText("11", (float)x, (float)y, skPaint);

            args.Surface.Canvas.DrawText(HH.ToString() + ":" + MM.ToString() + ":" + SS.ToString(), 0,15, skPaint);


            ////////////////////////////////////////////////////////////////////////////
            double RetX(int RS){

                return ( (skiaCanvas2.CanvasSize.Width  /2) + 85 * Math.Sin(RS*3.14/30)-7 );
            }

            double RetY(int RS){
                return ( (skiaCanvas2.CanvasSize.Height /2) - 85 * Math.Cos(RS*3.14/30)+1 );

            }            
            ////////////////////////////////////////////////////////////////////////////


        }



		void PaintSurface(object sender, SKPaintSurfaceEventArgs args){

            SKImageInfo info = args.Info;
            SKSurface surface = args.Surface;
            SKCanvas canvas = surface.Canvas;
                          
            // グラフ部背景色
            canvas.Clear(SKColors.WhiteSmoke);
            
            SKPaint A_LINE= new SKPaint{
	            Style =  SKPaintStyle.Stroke,
			    Color = new SKColor(0, 191, 200),
                IsAntialias=true,
                StrokeWidth = 3

            };

            SKPaint B_LINE= new SKPaint{
	            Style =  SKPaintStyle.StrokeAndFill,
			    Color = new SKColor(125, 55, 55),
                //  StrokeCap = (SKStrokeCap)10,
                IsAntialias=true,
                  
                StrokeWidth = 3

            };

            Moji(args);

            canvas.DrawCircle((float)skiaCanvas2.CanvasSize.Width  /2, (float)skiaCanvas2.CanvasSize.Height /2, 100,A_LINE);
            canvas.DrawCircle((float)skiaCanvas2.CanvasSize.Width  /2, (float)skiaCanvas2.CanvasSize.Height /2, 65,A_LINE);
            canvas.DrawCircle((float)skiaCanvas2.CanvasSize.Width  /2, (float)skiaCanvas2.CanvasSize.Height /2 ,30,A_LINE);  
            double y,x;
            
            // 秒針
            x=skiaCanvas2.CanvasSize.Width  / 2+  90* Math.Sin(SS*3.14/30);
            y=skiaCanvas2.CanvasSize.Height / 2 - 90* Math.Cos(SS*3.14/30);
    
            var cc=skiaCanvas2.CanvasSize.Width  / 2;
            var bb=skiaCanvas2.CanvasSize.Height / 2;
    
            canvas.DrawLine (cc,bb+3,(int)x,(int)y,B_LINE);
            // 短針
            x = (skiaCanvas2.CanvasSize.Width  /2) + 65 * Math.Sin(HH * 3.14 / 6 + MM * 3.14 / 360);
            y = (skiaCanvas2.CanvasSize.Height /2) - 65 * Math.Cos(HH * 3.14 / 6 + MM * 3.14 / 360);
            canvas.DrawLine (cc,bb+3,(int)x,(int)y,B_LINE);

            // 長針
            x = (skiaCanvas2.CanvasSize.Width  /2) + 90 * Math.Sin(MM * 3.14 / 30 + SS * 3.14 / 1800);
            y = (skiaCanvas2.CanvasSize.Height /2) - 90 * Math.Cos(MM * 3.14 / 30 + SS * 3.14 / 1800);
            canvas.DrawLine (cc,bb+3,(int)x,(int)y,B_LINE);
		}
	}
}
```

### 共通XAML

```xml
<Window x:Class="SkiaSharpSample.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:SkiaSharpSample"
        xmlns:skia="clr-namespace:SkiaSharp.Views.WPF;assembly=SkiaSharp.Views.WPF" 
        xmlns:wpf="clr-namespace:SkiaSharp.Views.WPF;assembly=SkiaSharp.Views.WPF" mc:Ignorable="d"
        Title="CLOCK SkiaSharp" Height="265" Width="265" Icon="icon.ico" Loaded="Window_Loaded">
    
    <Grid  >
        <wpf:SKElement x:Name="skiaCanvas2" PaintSurface="PaintSurface" />
    </Grid>
    
</Window>
```