【问题标题】:How to reset control after ScaleTransform animationScaleTransform动画后如何重置控制
【发布时间】:2017-10-31 15:28:25
【问题描述】:

我正在开发面向 PC 的 Windows 10 通用应用程序。我想重复运行动画(不是在“RepeatBehaviour”循环中,而是在发生其他事情后再次运行它),但我在动画完成后重置动画控件时遇到了困难。

情节提要中的动画之一是 TranslateTransform。完成后,我可以在代码中使用 Canvas.SetLeft 和 Canvas.SetTop 重新定位控件。但是,在我使用 ScaleTransform 动画“消失”一个控件后,该控件仍然不可见,我无法使其再次可见。更改控件的高度和宽度没有任何作用。

在 XAML 中使用 AutoReverse 确实解决了这个问题,但我不希望这对用户可见。控件应该“消失”。我想在下次运行之前在代码中重置控件,在幕后。

我的故事板和我正在制作动画的边框控件如下所示。这第一次工作正常。图像以一些旋转飞过屏幕,然后消失。第二次图像是不可见的,直到比例变换再次运行。

我尝试在第一个关键帧之前添加另一个 ScaleTransform 动画,以快速从 0 缩放到 1(我尝试了“0”或“0.1”的持续时间),但由于某种原因这破坏了整个事情。

我想知道 RenderTransformOrigin 是否与此有关,但不确定如何将其与 TransformGroup 一起使用。因此将其设置为 (0.5,0.5) 以使旋转居中。

任何帮助将不胜感激。

 <Storyboard x:Name="myStoryboard">
        <DoubleAnimationUsingKeyFrames
                        Storyboard.TargetName="myImage"
                        Storyboard.TargetProperty="(Canvas.Top)"
                        EnableDependentAnimation="False">
                        <SplineDoubleKeyFrame x:Name="MyTopSpline"   KeyTime="0:0:1.9"/>
                    </DoubleAnimationUsingKeyFrames>

                    <DoubleAnimationUsingKeyFrames
                        Storyboard.TargetName="myImage"
                        Storyboard.TargetProperty="(Canvas.Left)"
                        EnableDependentAnimation="False"">
                        <SplineDoubleKeyFrame x:Name="MyLeftSpline" KeyTime="0:0:1.9"/>
                    </DoubleAnimationUsingKeyFrames>

                    <DoubleAnimation Storyboard.TargetName="myImage" 
                             Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(RotateTransform.Angle)" 
                             From="0" To="360" BeginTime="0:0:1.0" Duration="0:0:1.9" />

                    <DoubleAnimation Storyboard.TargetName="myImage"
                                      Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[1].(ScaleTransform.ScaleX)" 
                             From="1" To="0" BeginTime="0:0:1.9" Duration="0:0:0.9" />
                    <DoubleAnimation Storyboard.TargetName="myImage"
                                      Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[1].(ScaleTransform.ScaleY)" 
                             From="1" To="0" BeginTime="0:0:1.9" Duration="0:0:0.9"  />


</Storyboard>

  <Border Name="myImage"  Height="244" Width="244" Canvas.Left="200" Canvas.Top="100" Visibility="Collapsed" 
RenderTransformOrigin=".5,.5">
        <Border.RenderTransform>
            <TransformGroup>
                    <RotateTransform Angle="0" />
                    <ScaleTransform ScaleX="1" ScaleY="1" />
                </TransformGroup>
         </Border.RenderTransform>
</Border>

【问题讨论】:

    标签: c# animation uwp storyboard windows-10-universal


    【解决方案1】:

    首先,让我们稍微清理一下您的代码。您应该使用名为CompositeTransform 的复合变换对象,而不是使用TransformGroup,因为它更容易使用。别忘了给它命名。

    <Border.RenderTransform>
        <CompositeTransform x:Name="myImageTransform" />
    </Border.RenderTransform>
    

    所以现在您的Storyboard 应该如下所示。请注意,我已为其添加了一个 myStoryboard_Completed 处理程序。

    <Storyboard x:Name="myStoryboard"
                Completed="myStoryboard_Completed">
        <DoubleAnimationUsingKeyFrames Storyboard.TargetName="myImage"
                                       Storyboard.TargetProperty="(Canvas.Top)">
            <SplineDoubleKeyFrame x:Name="MyTopSpline" KeyTime="0:0:1.9" />
        </DoubleAnimationUsingKeyFrames>
    
        <DoubleAnimationUsingKeyFrames Storyboard.TargetName="myImage"
                                       Storyboard.TargetProperty="(Canvas.Left)">
            <SplineDoubleKeyFrame x:Name="MyLeftSpline" KeyTime="0:0:1.9" />
        </DoubleAnimationUsingKeyFrames>
    
        <DoubleAnimation Storyboard.TargetName="myImage"
                         Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.Rotation)"
                         From="0"
                         To="360"
                         BeginTime="0:0:1.0"
                         Duration="0:0:1.9" />
    
        <DoubleAnimation Storyboard.TargetName="myImage"
                         Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleX)"
                         From="1"
                         To="0"
                         BeginTime="0:0:1.9"
                         Duration="0:0:0.9" />
        <DoubleAnimation Storyboard.TargetName="myImage"
                         Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleY)"
                         From="1"
                         To="0"
                         BeginTime="0:0:1.9"
                         Duration="0:0:0.9" />
    </Storyboard>
    

    在这个处理程序中,您需要做的就是重置所有的变换属性和画布偏移。

    private void myStoryboard_Completed(object sender, object e)
    {
        myImage.Visibility = Visibility.Collapsed;
    
        Canvas.SetTop(myImage, 100);
        Canvas.SetLeft(myImage, 200);
    
        myImageTransform.Rotation = 0;
        myImageTransform.ScaleX = myImageTransform.ScaleY = 1;
    }
    

    但这里有一个更好的方法。

    与其在后面的代码中做一些事情,为什么不将所有逻辑包装在同一个Storyboard 中?您只需使用DoubleAnimationUsingKeyFrames 为每个动画定义开始值和结束值

    <Storyboard x:Name="myStoryboard">
        <DoubleAnimationUsingKeyFrames Storyboard.TargetName="myImage"
                                       Storyboard.TargetProperty="(Canvas.Top)">
            <SplineDoubleKeyFrame KeyTime="0:0:0" Value="100" />
            <SplineDoubleKeyFrame x:Name="MyTopSpline" KeyTime="0:0:1.9" Value="100" />
        </DoubleAnimationUsingKeyFrames>
    
        <DoubleAnimationUsingKeyFrames Storyboard.TargetName="myImage"
                                       Storyboard.TargetProperty="(Canvas.Left)">
            <SplineDoubleKeyFrame KeyTime="0:0:0" Value="200" />
            <SplineDoubleKeyFrame x:Name="MyLeftSpline" KeyTime="0:0:1.9" Value="200" />
        </DoubleAnimationUsingKeyFrames>
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.Rotation)"
                                       Storyboard.TargetName="myImage">
            <EasingDoubleKeyFrame KeyTime="0" Value="0" />
            <EasingDoubleKeyFrame KeyTime="0:0:1" Value="0" />
            <EasingDoubleKeyFrame KeyTime="0:0:2.9" Value="360" />
        </DoubleAnimationUsingKeyFrames>
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleX)"
                                       Storyboard.TargetName="myImage">
            <EasingDoubleKeyFrame KeyTime="0" Value="1" />
            <EasingDoubleKeyFrame KeyTime="0:0:1" Value="1" />
            <EasingDoubleKeyFrame KeyTime="0:0:1.9" Value="1" />
            <EasingDoubleKeyFrame KeyTime="0:0:2.8" Value="0" />
        </DoubleAnimationUsingKeyFrames>
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleY)"
                                       Storyboard.TargetName="myImage">
            <EasingDoubleKeyFrame KeyTime="0" Value="1" />
            <EasingDoubleKeyFrame KeyTime="0:0:1" Value="1" />
            <EasingDoubleKeyFrame KeyTime="0:0:1.9" Value="1" />
            <EasingDoubleKeyFrame KeyTime="0:0:2.8" Value="0" />
        </DoubleAnimationUsingKeyFrames>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
                                       Storyboard.TargetName="myImage">
            <DiscreteObjectKeyFrame KeyTime="0">
                <DiscreteObjectKeyFrame.Value>
                    <Visibility>Visible</Visibility>
                </DiscreteObjectKeyFrame.Value>
            </DiscreteObjectKeyFrame>
            <DiscreteObjectKeyFrame KeyTime="0:0:3">
                <DiscreteObjectKeyFrame.Value>
                    <Visibility>Collapsed</Visibility>
                </DiscreteObjectKeyFrame.Value>
            </DiscreteObjectKeyFrame>
        </ObjectAnimationUsingKeyFrames>
    </Storyboard>
    

    希望这会有所帮助!

    【讨论】:

    • 谢谢。 CompositeTransform 肯定比 TransformGroup 更容​​易使用,但不幸的是它不能解决问题。在下一次尺度变换运行之前,图像仍然不可见(完成事件中的代码确实运行)。似乎只是更改 ScaleX 和 ScaleY 值并不会真正重置控件。另外,我不能在 XAML 中做所有事情,因为很多值都是在运行时计算的。我想我需要强制对象重新缩放到 X=Y=1 但不知道如何...
    • 我想看这个问题的现场演示,因为上面的代码在我的项目中确实有效。顺便说一句,您是否在回调中将Visibility 设置回Visible
    • 其实有一个简单的方法来调试你的问题。您以前尝试过 Live Visual Tree 吗?你可以在那里检查myImage,在Live Property Explorer中,你可以找到所有的transformation、Visibility、Canvas.Left值并直接在那里修改它们,然后你应该能够找出哪个是计算错误的。
    • 它不是可见性,因为当比例转换运行时控件出现。一旦我将它缩放到零,它直到下一次缩放变换才会恢复。今晚我将尝试使用可视化树进行故障排除...
    • 顺便说一句,如果我在比例转换中使用 AutoRestore,它可以解决问题。我只是不想让用户看到它......
    【解决方案2】:

    将这行代码添加到 StoryBoard 完成事件解决了这个问题:

    MyStoryboard.Stop();
    

    【讨论】:

    猜你喜欢
    • 2015-10-11
    • 1970-01-01
    • 2019-11-24
    • 1970-01-01
    • 2013-06-22
    • 1970-01-01
    • 1970-01-01
    • 2017-08-28
    • 1970-01-01
    相关资源
    最近更新 更多