在WPF中仅使用XAML代码创建数字时钟

时间:2019-03-26 05:24:58

标签: wpf xaml

我想知道是否可以使用动画(没有背景代码标签)在xaml中创建数字时钟

可以通过矩阵转换将当前时间转换为角度来实现模拟时钟,但是数字时钟不能像这样操作。我尝试了很多方法,但是没有用。有人知道是否有实现它的好方法吗?

模拟时钟实现

<Window>
    <Window.Resources>
        <FrameworkElement x:Key="time" Tag={x:Static s:DateTime.Now}/>


        <TransformGroup x:Key="transformHour">
            <TranslateTransform X="{Binding Source={StaticResource time},Path=Tag.Hour}"
                                Y="{Binding Source={StaticResource time},Path=Tag.Minute}"/>
            <MatrixTransform Matrix="30 0 0.5 0 0 0"/>
        </TransformGroup>

        <TransformGroup x:Key="transformMinute">
            <TranslateTransform X="{Binding Source={StaticResource time},Path=Tag.Minute}"
                                Y="{Binding Source={StaticResource time},Path=Tag.Second}"/>
            <MatrixTransform Matrix="6 0 0.1 0 0 0"/>
        </TransformGroup>

        <TransformGroup x:Key="transformSecond">
            <TranslateTransform X="{Binding Source={StaticResource time},Path=Tag.Second}"/>
            <MatrixTransform Matrix="6 0 0 0 0 0"/>
        </TransformGroup>

        <Style TargetType="{x:Type Path}">
            <Setter Property="Stroke" 
                    Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"/>
            <Setter Property="StrokeThickness" Value="3"/>
            <Setter Property="StrokeDashCap" Value="Triangle"/>
        </Style>

    </Window.Resources>

    <Viewbox>
        <Canvas Width="200" Height="200">
            <Canvas.RenderTransform>
                <TranslateTransform X="100" Y="100"/>
            </Canvas.RenderTransform>

            <Path Data="M 0 -90 A 90 90 0 1 1 -0.01 -90"
                  StrokeDashArray="0 3.14157" />

            <Path Data="M 0 -90 A 90 90 0 1 1 -0.01 -90"
                  StrokeDashArray="0 7.854"
                  StrokeThickness="6"/>

            <Border Background="LightBlue" Width="10" Height="80" RenderTransformOrigin="0.5 0">
                <Border.RenderTransform>
                    <TransformGroup>
                        <RotateTransform x:Name="bor_Second" Angle="{Binding Source={StaticResource transformSecond},Path=Value.OffsetX}"/>
                        <RotateTransform Angle="180"/>
                    </TransformGroup>
                </Border.RenderTransform>
            </Border>

            <Border Background="LightGreen" Width="10" Height="60" RenderTransformOrigin="0.5 0">
                <Border.RenderTransform>
                    <TransformGroup>
                        <RotateTransform x:Name="bor_Minute" Angle="{Binding Source={StaticResource transformMinute},Path=Value.OffsetX}"/>
                        <RotateTransform Angle="180"/>
                    </TransformGroup>
                </Border.RenderTransform>
            </Border>

            <Border Background="LightGray" Width="10" Height="40" RenderTransformOrigin="0.5 0">
                <Border.RenderTransform>
                    <TransformGroup>
                        <RotateTransform x:Name="bor_Hour" Angle="{Binding Source={StaticResource transformHour},Path=Value.OffsetX}"/>
                        <RotateTransform Angle="180"/>
                    </TransformGroup>
                </Border.RenderTransform>
            </Border>

        </Canvas>
    </Viewbox>
    <Window.Triggers>
        <EventTrigger RoutedEvent="Loaded">
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimation Storyboard.TargetName="bor_Hour"
                                    Storyboard.TargetProperty="Angle"
                                    IsAdditive="True"
                                    Duration="12:0:0"
                                    From="0" To="360"
                                    RepeatBehavior="Forever"/>
                    <DoubleAnimation Storyboard.TargetName="bor_Minute"
                                    Storyboard.TargetProperty="Angle"
                                    IsAdditive="True"
                                    Duration="1:0:0"
                                    From="0" To="360"
                                    RepeatBehavior="Forever"/>
                    <DoubleAnimation Storyboard.TargetName="bor_Second"
                                    Storyboard.TargetProperty="Angle"
                                    IsAdditive="True"
                                    Duration="0:1:0"
                                    From="0" To="360"
                                    RepeatBehavior="Forever"
                                    />
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Window.Triggers>
</Window>

数字时钟(有错误),我觉得使用这个想法比较麻烦。有人知道是否有实现它的好方法吗?

<Window>
    <Window.Resources>

        <!--current time-->
        <FrameworkElement x:Key="time" Tag="{x:Static s:DateTime.Now}"/>


        <!--Current minutes remaining seconds-->
        <TransformGroup x:Key="transformSecond">
            <TranslateTransform X="{Binding Source={StaticResource time},Path=Tag.Second}" Y="60"/>
            <MatrixTransform Matrix="-1 0 1 0 0 0"/>
        </TransformGroup>

        <!--Remaining seconds interval-->
        <FrameworkElement x:Key="timeSpanSecond" 
                          Tag="{Binding Source={StaticResource transformSecond},Path=Value.OffsetX,StringFormat={}{0:F0}}"/>


        <!--Current hours remaining minutes-->
        <TransformGroup x:Key="transformMinute">
            <TranslateTransform X="{Binding Source={StaticResource time},Path=Tag.Minute}" Y="60"/>
            <MatrixTransform Matrix="-1 1 1 0 0 1"/>
        </TransformGroup>

        <!--Remaining minute interval-->
        <FrameworkElement x:Key="timeSpanMinute" 
                          Tag="{Binding Source={StaticResource transformMinute},Path=Value.OffsetX,StringFormat={}{0:F0}}"/>

        <!--Next minute-->
        <FrameworkElement x:Key="minuteNext" 
                          Tag="{Binding Source={StaticResource transformMinute},Path=Value.OffsetY}"/>


        <!--Hours remaining on the day-->
        <TransformGroup x:Key="transformHour">
            <TranslateTransform X="{Binding Source={StaticResource time},Path=Tag.Hour}" Y="24"/>
            <MatrixTransform Matrix="-1 1 1 0 0 1"/>
        </TransformGroup>


        <!--Remaining hours interval-->
        <FrameworkElement x:Key="timeSpanHour" 
                          Tag="{Binding Source={StaticResource transformHour},Path=Value.OffsetX,StringFormat={}{0:F0}}"/>

        <!--Next hour-->
        <FrameworkElement x:Key="hourNext" 
                          Tag="{Binding Source={StaticResource transformHour},Path=Value.OffsetY}"/>




    </Window.Resources>

    <Grid>
        <!--Width:Current seconds-->
        <!--Text:Current remaining seconds(TimeSpan)-->
        <TextBlock x:Name="tbk_Second" Visibility="Hidden" 
                   Width="{Binding Source={StaticResource time},Path=Tag.Second}"
                   Text="{Binding Source={StaticResource timeSpanSecond},StringFormat=0:0:{0},Path=Tag}"/>


        <TextBlock x:Name="tbk_Minute" Visibility="Hidden"  
                   Width="{Binding Source={StaticResource time},Path=Tag.Minute}"       
                   Text="{Binding Source={StaticResource timeSpanMinute},StringFormat=0:{0}:0,Path=Tag}">
        </TextBlock>


        <TextBlock x:Name="tbk_Hour" Visibility="Hidden" 
                   Width="{Binding Source={StaticResource time},Path=Tag.Hour}"       
                   Text="{Binding Source={StaticResource timeSpanHour},StringFormat={}{0}:0:0,Path=Tag}"/>

        <TextBlock VerticalAlignment="Center" HorizontalAlignment="Center">
            <Run Text="{Binding ElementName=tbk_Hour,Path=Width,StringFormat={}{0:F0}}"/>
            <Run Text=":"/>
            <Run Text="{Binding ElementName=tbk_Minute,Path=Width,StringFormat={}{0:F0}}"/>
            <Run Text=":"/>
            <Run Text="{Binding ElementName=tbk_Second,Path=Width,StringFormat={}{0:F0}}"/>
        </TextBlock>


    </Grid>

    <Window.Triggers>
        <EventTrigger RoutedEvent="Loaded">
            <BeginStoryboard>
                <Storyboard >

                    <DoubleAnimation Storyboard.TargetName="tbk_Hour"
                                    Storyboard.TargetProperty="Width"
                                    BeginTime="{Binding ElementName=tbk_Minute,Path=Text}"
                                    Duration="{Binding ElementName=tbk_Hour,Path=Text}"
                                    From="{Binding Source={StaticResource hourNext},Path=Tag}" 
                                    To="23"/>

                    <DoubleAnimation Storyboard.TargetName="tbk_Hour"
                                    Storyboard.TargetProperty="Width"
                                    BeginTime="{Binding ElementName=tbk_Hour,Path=Text}"
                                    Duration="24:0:0"
                                    From="0" 
                                    To="23"        
                                    RepeatBehavior="Forever"/>


                    <DoubleAnimation Storyboard.TargetName="tbk_Minute"
                                    Storyboard.TargetProperty="Width"
                                    BeginTime="{Binding ElementName=tbk_Second,Path=Text}"
                                    Duration="{Binding ElementName=tbk_Minute,Path=Text}"
                                    From="{Binding Source={StaticResource minuteNext},Path=Tag}" 
                                    To="59"/>

                    <DoubleAnimation Storyboard.TargetName="tbk_Minute"
                                    Storyboard.TargetProperty="Width"
                                    BeginTime="{Binding ElementName=tbk_Minute,Path=Text}"
                                    Duration="1:0:0"
                                    From="0" 
                                    To="59"        
                                    RepeatBehavior="Forever"/>


                    <DoubleAnimation 
                                    Storyboard.TargetName="tbk_Second"
                                    Storyboard.TargetProperty="Width"
                                    Duration="{Binding ElementName=tbk_Second,Path=Text}"                                             
                                    From="{Binding Source={StaticResource time},Path=Tag.Second}" 
                                    To="59" 
                                    />
                    <DoubleAnimation Storyboard.TargetName="tbk_Second"
                                    Storyboard.TargetProperty="Width"
                                    BeginTime="{Binding ElementName=tbk_Second,Path=Text}"
                                    Duration="0:1:0"
                                    From="0" 
                                    To="59"        
                                    RepeatBehavior="Forever"/>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Window.Triggers>

</Window>

2 个答案:

答案 0 :(得分:0)

也许这是您想要的答案:)

<Window x:Class="WpfApp6.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:system="clr-namespace:System;assembly=System.Runtime"
        mc:Ignorable="d"
        Title="MainWindow"
        Height="450"
        Width="800">
    <Grid>
        <Grid.Resources>
            <!--Set x: share to get the latest every time-->
            <system:DateTime x:Key="DateTime"
                            x:Shared="False" />
            <Storyboard x:Key="Storyboard">
                <!--Use keyframe animation to update datetime -->
                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="DataContext"
                                            Duration="0:0:1"
                                            RepeatBehavior="Forever"
                                            AutoReverse="False">
                    <DiscreteObjectKeyFrame KeyTime="50%"
                                            Value="{StaticResource DateTime}" />
                </ObjectAnimationUsingKeyFrames>
            </Storyboard>
        </Grid.Resources>
        <!--Get datetime from DataContext-->
        <TextBlock Text="{Binding RelativeSource={RelativeSource Self},Path=DataContext.Now}"
                DataContext="{StaticResource DateTime}">
            <TextBlock.Triggers>
                <EventTrigger RoutedEvent="Loaded">
                    <BeginStoryboard Storyboard="{StaticResource Storyboard}" />
                </EventTrigger>
            </TextBlock.Triggers>
        </TextBlock>
    </Grid>
</Window>

答案 1 :(得分:-1)

我建议您基于文本块和类似这样的合适字体来做到这一点:

https://www.keshikan.net/fonts-e.html

您的文本块绑定到可以由调用'DateTime.Now();'的异步函数设置的属性。 这是一个XAML示例:

            <Border HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="0,0,0,40" Background="DarkGray" BorderThickness="1,1,0,0" BorderBrush="Gray">
                <Grid>  
                    <!-- Displays the actual time in red-->
                    <StackPanel Orientation="Horizontal" Margin="2">
                        <TextBlock Opacity="0.6" Foreground="Red" FontSize="20" Text="{Binding Hour, FallbackValue=00, StringFormat=00}" FontFamily="DSEG7 Classic Mini" ></TextBlock>
                        <TextBlock Opacity="0.6" Foreground="Red" FontSize="20" FontFamily="DSEG7 Classic Mini" >:</TextBlock>
                        <TextBlock Opacity="0.6" Foreground="Red" FontSize="20" Text="{Binding Min, FallbackValue=00, StringFormat=00}" FontFamily="DSEG7 Classic Mini" ></TextBlock>
                        <TextBlock Opacity="0.6" Foreground="Red" FontSize="20" FontFamily="DSEG7 Classic Mini">:</TextBlock>
                        <TextBlock Opacity="0.6" Foreground="Red" FontSize="20" Text="{Binding Sec, FallbackValue=00, StringFormat=00}" FontFamily="DSEG7 Classic Mini" ></TextBlock>
                    </StackPanel>
                    <!-- Creates a Glow Effect -->
                    <StackPanel Orientation="Horizontal" Margin="2">
                        <StackPanel.Effect>
                            <BlurEffect KernelType="Gaussian" Radius="3"/>
                        </StackPanel.Effect>
                        <TextBlock Foreground="Red" FontSize="20" Text="{Binding Hour, FallbackValue=00, StringFormat=00}" FontFamily="DSEG7 Classic Mini" ></TextBlock>
                        <TextBlock Foreground="Red" FontSize="20" FontFamily="DSEG7 Classic Mini" >:</TextBlock>
                        <TextBlock Foreground="Red" FontSize="20" Text="{Binding Min, FallbackValue=00, StringFormat=00}" FontFamily="DSEG7 Classic Mini" ></TextBlock>
                        <TextBlock Foreground="Red" FontSize="20" FontFamily="DSEG7 Classic Mini">:</TextBlock>
                        <TextBlock Foreground="Red" FontSize="20" Text="{Binding Sec, FallbackValue=00, StringFormat=00}" FontFamily="DSEG7 Classic Mini" ></TextBlock>
                    </StackPanel>
                    <!-- Creates the effect of turned of segments -->
                    <StackPanel Orientation="Horizontal" Margin="2">
                        <TextBlock Opacity="0.1" FontSize="20" Text="88" FontFamily="DSEG7 Classic Mini" ></TextBlock>
                        <TextBlock Opacity="0.1" FontSize="20" FontFamily="DSEG7 Classic Mini" >:</TextBlock>
                        <TextBlock Opacity="0.1" FontSize="20" Text="88" FontFamily="DSEG7 Classic Mini" ></TextBlock>
                        <TextBlock Opacity="0.1" FontSize="20" FontFamily="DSEG7 Classic Mini">:</TextBlock>
                        <TextBlock Opacity="0.1" FontSize="20" Text="88" FontFamily="DSEG7 Classic Mini" ></TextBlock>
                    </StackPanel>
                </Grid>
            </Border>

enter image description here

仅使用一个文本块和一个字符串格式会更加容易,但是这个示例我已经在::