简体   繁体   中英

WPF: Detect Animation or Cancel Timeline.Completed Event? How?

I'm moving 3d camera like this:

    Point3DAnimation pa;

    // Triggered by user click
    void MoveCamera(object sender, EventArgs e)
    {

        pa = new Point3DAnimation(myPoint3D, TimeSpan.FromMilliseconds(2000));
        pa.Completed += new EventHandler(pa_Completed);
        Camera.BeginAnimation(PerspectiveCamera.PositionProperty, pa); // anim#1
    }

    // we're in place. do some idle animation
    void pa_Completed(object sender, EventArgs e)
    {
        pa = new Point3DAnimation(myPoint3Ddz, TimeSpan.FromMilliseconds(5000));
        Camera.BeginAnimation(PerspectiveCamera.PositionProperty, pa); // anim#2
    }
  1. User clicks.
  2. Camera moves to choosen position (anim#1).
  3. When anim#1 ends anim#2 is played.

Everything is ok... until user triggers MoveCamera when previous anim#1 is not finished.

In that case:

  1. New anim#1 is starting.
  2. Completed event of old anim#1 is triggered.
  3. anim#2 is started instatntly (overlapping new anim#1).

2 & 3 are wrong here. How i can avoid that?

I think that pa_Completed() should detect that new anim#1 is already playing, or MoveCamera() should unregister Complete event from old anim#1. But what the right way to do it?

If the goal is to chain two animations together, let WPF do the heavy lifting by using the Point3DAnimationUsingKeyFrames class.

First, build the key frame animation in XAML (it's a bear to do it in code):

  <Window.Resources>
    <Point3DAnimationUsingKeyFrames x:Key="CameraMoveAnimation" Duration="0:0:7">
      <LinearPoint3DKeyFrame KeyTime="28%" />
      <LinearPoint3DKeyFrame KeyTime="100%" />
    </Point3DAnimationUsingKeyFrames>
  </Window.Resources>

Next, consume it and set the actual Point3D values (using your code names):

private void MoveCamera(object sender, EventArgs e) {
    Point3DAnimationUsingKeyFrames cameraAnimation = 
        (Point3DAnimationUsingKeyFrames)Resources["CameraMoveAnimation"];
    cameraAnimation.KeyFrames[0].Value = myPoint3D;
    cameraAnimation.KeyFrames[1].Value = myPoint3dz;
    Camera.BeginAnimation(PerspectiveCamera.PositionProperty, cameraAnimation);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM