如何检测何时停止动画并更新属性?

问题描述:

如果我在可视图层中创建并启动动画,则可以使用StopAnimation停止动画。但是当我这样做的时候,似乎需要一段时间才会停止动画,并且使用最新值更新属性。有没有办法解决这个问题?在下面的代码中,我等待10毫秒,但只有有时才有效。如何检测何时停止动画并更新属性?

public sealed partial class MainPage : Page 
{ 
    SpriteVisual MyVisual; 

    public MainPage() 
    { 
     this.InitializeComponent(); 

     PointerReleased += MainPage_PointerReleased; 
    } 


    protected override void OnNavigatedTo(NavigationEventArgs e) 
    { 
     base.OnNavigatedTo(e); 

     var compositor = ElementCompositionPreview.GetElementVisual(this).Compositor; 

     MyVisual = compositor.CreateSpriteVisual(); 

     MyVisual.Size = new Vector2(80, 80); 
     MyVisual.Offset = new Vector3(50, 50, 0); 
     MyVisual.Brush = compositor.CreateColorBrush(Colors.Green); 

     ElementCompositionPreview.SetElementChildVisual(this, MyVisual); 

     var animation = compositor.CreateVector3KeyFrameAnimation(); 
     animation.InsertKeyFrame(1, new Vector3(300, 50, 0)); 
     animation.Duration = TimeSpan.FromSeconds(3); 
     animation.IterationBehavior = AnimationIterationBehavior.Forever; 

     MyVisual.StartAnimation(nameof(MyVisual.Offset), animation); 
    } 

    private async void MainPage_PointerReleased(object sender, PointerRoutedEventArgs e) 
    { 
     System.Diagnostics.Debug.WriteLine("Position when animation running: " + MyVisual.Offset); 

     MyVisual.StopAnimation(nameof(MyVisual.Offset)); 

     await Task.Delay(10); 

     System.Diagnostics.Debug.WriteLine("Position when animation stopped: " + MyVisual.Offset); 
    } 
} 

您可以使用CompositionScopedBatch来解决这个问题。有一点需要注意的是,如果您有无数次迭代(我不知道为什么),那么Completed事件会立即触发。这里是一个样本:

public sealed partial class MainPage : Page 
{ 
    SpriteVisual MyVisual; 
    CompositionScopedBatch ScopedBatch; 

    public MainPage() 
    { 
     this.InitializeComponent(); 

     PointerReleased += MainPage_PointerReleased; 
    } 

    protected override void OnNavigatedTo(NavigationEventArgs e) 
    { 
     base.OnNavigatedTo(e); 

     var compositor = ElementCompositionPreview.GetElementVisual(this).Compositor; 

     MyVisual = compositor.CreateSpriteVisual(); 

     MyVisual.Size = new Vector2(80, 80); 
     MyVisual.Offset = new Vector3(50, 50, 0); 
     MyVisual.Brush = compositor.CreateColorBrush(Colors.Green); 

     ElementCompositionPreview.SetElementChildVisual(this, MyVisual); 

     ScopedBatch = compositor.CreateScopedBatch(CompositionBatchTypes.Animation); 

     var animation = compositor.CreateVector3KeyFrameAnimation(); 
     animation.InsertKeyFrame(1, new Vector3(300, 50, 0)); 
     animation.Duration = TimeSpan.FromSeconds(3); 
     // animation.IterationBehavior = AnimationIterationBehavior.Forever; 
     // CompositionScopedBatch.Completed is triggered immediately if Infinite is used. 
     // Use many iterations instead. 
     animation.IterationBehavior = AnimationIterationBehavior.Count; 
     animation.IterationCount = 1000000; 

     MyVisual.StartAnimation(nameof(MyVisual.Offset), animation); 

     ScopedBatch.Completed += CompositionScopedBatch_Completed; 

     ScopedBatch.End(); 
    } 

    private void CompositionScopedBatch_Completed(object sender, CompositionBatchCompletedEventArgs args) 
    { 
     System.Diagnostics.Debug.WriteLine("Position when batch completed: " + MyVisual.Offset); 
    } 

    private void MainPage_PointerReleased(object sender, PointerRoutedEventArgs e) 
    { 
     System.Diagnostics.Debug.WriteLine("Position when animation running: " + MyVisual.Offset); 

     MyVisual.StopAnimation(nameof(MyVisual.Offset)); 
    } 
}