如何检测何时停止动画并更新属性?
问题描述:
如果我在可视图层中创建并启动动画,则可以使用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));
}
}