连续动画

基础的Storyboard、时间线什么的概念就不在这里写了,因为这个博客也就是我自己记录自己学习的历程,我还没到可以教别人的程度
用C#代码或者Xaml画一条线是很容易,但是要让线慢慢的一点点变长呢?用Timer计时器每隔一段时间修改line的宽度吗?不说Timer的时间精度问题,这样做出来想必也没有那么流畅的效果

目标效果

在这里插入图片描述

Blend实现

先创建一个Line的对象,放入Canvas容器内

    <Line x:Name="line" X1="50" Y1="150" X2="500" Y2="150" Stroke="Green" StrokeThickness="1" Width="500"/>

然后在对象和时间线窗口中,点击图中的按钮,创建一个新的Stroyboard
在这里插入图片描述

在时间点0秒处,创建关键帧,最右侧的line对象属性窗口中设置width属性为0
在这里插入图片描述

在这里插入图片描述

同理,时间点5秒处,创建关键帧,width属性设置为line的最终宽度,点播放按钮预览效果

动画的调用

两种方法调用动画,一种在后台找到对应的storyboard资源使用start方法调用,另一种使用Blend直接在xaml中调用触发器

  • 后台代码
	var storyboard = (Storyboard)this.FindResources("Storyboard1");
	storyboard.Start();
  • xaml触发器
    在这里插入图片描述

如下代码是Blend帮忙生成的

    <Window.Triggers>
            <EventTrigger RoutedEvent="FrameworkElement.Loaded">
                <BeginStoryboard Storyboard="{StaticResource openStoryboard}"/>
                <BeginStoryboard Storyboard="{StaticResource Storyboard1}"/>
                <BeginStoryboard Storyboard="{StaticResource pathStoryboard}"/>
            </EventTrigger>
        </Window.Trigger>

等待效果

使用上次一模一样的操作,从阿里矢量图标库选取一个进度条的图片,然后时间点0设置角度为0,时间点3设置角度360,也可以设置相同的时间间隔转动不同的角度达到变速效果
在这里插入图片描述

    <Storyboard x:Key="proStoryboard" RepeatBehavior="Forever" AutoReverse="False">
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)" Storyboard.TargetName="proimage">
            <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
            <EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="60"/>
            <EasingDoubleKeyFrame KeyTime="0:0:0.4" Value="180"/>
            <EasingDoubleKeyFrame KeyTime="0:0:0.6" Value="240"/>
            <EasingDoubleKeyFrame KeyTime="0:0:0.8" Value="300"/>
            <EasingDoubleKeyFrame KeyTime="0:0:1.0" Value="360"/>
            <!--<EasingDoubleKeyFrame KeyTime="0:0:1.2" Value="360"/>-->
        </DoubleAnimationUsingKeyFrames>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="proimage">
            <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}"/>
            <DiscreteObjectKeyFrame KeyTime="0:0:1.0" Value="{x:Static Visibility.Hidden}"/>
        </ObjectAnimationUsingKeyFrames>
    </Storyboard>

路径动画

要想自己创建的对象按照某种路线移动,有两种方法,一种是上面提到的关键帧,某一时间点设置起始位置,然后设置不同的时间点拖动到不同的位置,造成可以移动的动画,但是这种方法弊端在于不能随心所欲的控制移动的位置,比如要想绕个圈那得设置多少个关键帧,而且弧度还不平滑,因为它只是针对TranslateTransform.X/Y属性,第二种方法就是使用路径动画,这种可以自己画好path,可以精确控制

Blend实现

        <PathGeometry x:Key="PathGeometry1" Figures="M711.5,124 C711.5,124 628.5,257 766.5,221 904.5,185 1255.5025,96.499919 936.00088,146.00007 616.49922,195.50021 883.50077,102.49994 883.50077,102.49994 883.50077,102.49994 734.99988,-76.000585 771.00009,82.999882 807.00031,242.00035 942.00112,230.00031 942.00112,230.00031"/>

上面的代码是使用Blend的钢笔工具画出的一段路径,如下图
在这里插入图片描述

  • DoubleAnimationUsingPath 路径动画的标签
  • Duration 动画的时间间隔
  • TargetName 动画操作的对象名
  • TargetProperty 动画操作的属性,如放入Canvas容器内,可以为Canvs.Left/Top,不是的话属性设置为TranslateTransform.X/Y
  • Source 绑定的Path的X或者Y
  • PathGeometry 路径动画的路径

记不得标签的话,随便输入一个x或者y后Blend生成的代码中修改即可
在这里插入图片描述

    <Storyboard x:Name="storyboard" x:Key="pathStoryboard" AutoReverse="True" RepeatBehavior="Forever">
        <!--两种方法实现路径动画-->

        <!--<DoubleAnimationUsingPath Storyboard.TargetProperty="(Canvas.Left)" Duration="0:0:3" PathGeometry="{StaticResource PathGeometry1}" Storyboard.TargetName="movebtn" Source="X"/>-->
        <!--<DoubleAnimationUsingPath Storyboard.TargetProperty="(Canvas.Top)" Duration="0:0:3" PathGeometry="{StaticResource PathGeometry1}" Storyboard.TargetName="movebtn" Source="Y"/>-->
        <DoubleAnimationUsingPath Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Duration="0:0:3" PathGeometry="{StaticResource PathGeometry1}" Storyboard.TargetName="movebtn" Source="X"/>
        <DoubleAnimationUsingPath Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)" Duration="0:0:3" PathGeometry="{StaticResource PathGeometry1}" Storyboard.TargetName="movebtn" Source="Y"/>
    </Storyboard>

效果演示

大方块使用第一种方法,小方块使用第二种方法
在这里插入图片描述


启动、关闭动画

Blend实现

也是使用连续动画的方式,操作的对象变成了window,操作的属性是width,控制窗体达到一个慢慢向右铺开的效果,但是如果设置窗体居中,铺开后窗体不会再正中,这个暂时没有解决

    <!--控制window的旋转和缩放-->
    <Window.RenderTransform>
        <TransformGroup>
            <ScaleTransform x:Name="scale" ScaleX="1" ScaleY="1"></ScaleTransform>
            <RotateTransform x:Name="rotate" Angle="0"></RotateTransform>
        </TransformGroup>
    </Window.RenderTransform>

对于Window来说,右侧的属性窗口没有转换选项,但其实可以转换操作,不过要用代码实现,操作属性width可以实现铺开效果,而且右侧属性窗口是有width属性的,控制ScaleX和Scale Y属性从0-1控制缩放

    <Storyboard x:Key="openStoryboard">
            <DoubleAnimation Storyboard.TargetProperty="(FrameworkElement.Width)" From="0" To="1200" Duration="0:0:1" Storyboard.TargetName="window"/>
            <!--<DoubleAnimation Storyboard.TargetProperty="ScaleX" From="0.1" To="1" Duration="0:0:1" Storyboard.TargetName="scale"/>-->
            <!--<DoubleAnimation Storyboard.TargetProperty="ScaleY" From="0.1" To="1" Duration="0:0:1" Storyboard.TargetName="scale"/>-->
    </Storyboard>

关闭也是操作width,不过是从展开后的宽度变为0,然后加上旋转,1秒转动720度(2圈),操作Opacity属性控制渐隐渐显效果,从1-0为渐隐

    <Storyboard x:Key="closeStoryboard">
            <DoubleAnimation Storyboard.TargetProperty="(FrameworkElement.Width)" From="1200" To="0" Duration="0:0:1" Storyboard.TargetName="window"/>
            <DoubleAnimation Storyboard.TargetProperty="Angle" From="0" To="720" Duration="0:0:1" Storyboard.TargetName="rotate"/>
            <DoubleAnimation Storyboard.TargetProperty="Opacity" From="1" To="0" Duration="0:0:1" Storyboard.TargetName="grid"/>
    </Storyboard>

启动动画Loaded事件加载,关闭动画需要在Closing事件中加载关闭动画然后阻止窗体关闭,在关闭动画执行结束后关闭窗体

    public MainWindow()
    {
        InitializeComponent();
        closeStoryboard = (Storyboard)this.FindResource("closeStoryboard");
        closeStoryboard.Completed += (c, d) => Application.Current.Shutdown(); ;
    }

    private void window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
    {
        closeStoryboard.Begin();
        e.Cancel = true;
    }

如果启动动画、关闭动画出现黑色背景,多半是因为window的style没有设置为None,而且AllowsTransparency设置为true,标题栏需要自己画

效果演示

在这里插入图片描述

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐