This project is read-only.

How to repeat an animation?

Aug 12, 2012 at 5:38 AM

i tried doing this but doesn't work...

 

easeObject.OnComplete((eo, d) =>
                                      {
                                          eo.Finish();
                                          eo.Start();
                                      });
Jun 29, 2013 at 4:17 PM
Two major things;
  1. Starting an EaseObject over again without changing any values will effectively do nothing since you've already set the start values to the destination values.
  2. Even if you change that, I just checked and my code has a fatal bug that won't let you do any of that because it kills the animation internals AFTER it calls on the onComplete method. My bad...
The bug in EaseObject.Finish
            if (ActiveCount > 0)
            {
                if (Update != null) Update(this, PercentEase);
                if (Complete != null) Complete(this, PercentEase);
            }
            return Stop();
The potential fix for EaseObject.Finish
            if (ActiveCount > 0)
            { 
                if (Update != null) Update(this, PercentEase);
                Stop();
                if (Complete != null) Complete(this, PercentEase);
                return this;
            }
            else
            {
                return Stop();
            }
Jun 29, 2013 at 4:30 PM
Edited Jun 29, 2013 at 4:30 PM
[REQUIRES THE ABOVE FIX IN EaseObject.Finish]

To solve the repeat issue using your sample, lets take a random movement example.

Because the position will change each call, we need to wrap the destination call. For simplicity we'll use a Func<double>
    Func<double> rX = () => _rnd.NextDouble() * LayoutRoot.ActualWidth;
    Func<double> rY = () => _rnd.NextDouble() * LayoutRoot.ActualHeight;
    // Get random destination
    double x = rX();
    double y = rY();

    double delay = i * .02;
    double time = .6;
    PercentHandler ease = AnimationTransitions.CubicEaseOut;
                     
    EaseObject eo = ball.SlideTo(x, y, time, ease, delay); 
In the OnComplete, we'll need to reset the destination values. Do do that, we can loop through the current properties, find our position values and set them to new randoms.
  eo.OnComplete((easeObject, percent) =>
  { 
        // set the position values to new random location
        foreach (var pair in easeObject.Props)
        {
            if (pair.Value.Name == "x") pair.Value.ValueEnd = rX();
            else if (pair.Value.Name == "y") pair.Value.ValueEnd = rY(); 
        }

        // start the animation over!
        easeObject.Start();
  });
Jun 29, 2013 at 5:20 PM
[Alternate Solution w/Existing Code]

Here is an alternate that works with the current code and allows for number of loops. The reason this will work is because it's not trying to recycle the old ease object - a new ease is created and hijacks control over the properties.

The goal here is to move a ball to a random location 3 times inside LayoutRoot.

First, create a Func for new position values so we can test changing values
    Func<double> rX = () => _rnd.NextDouble() * LayoutRoot.ActualWidth;
    Func<double> rY = () => _rnd.NextDouble() * LayoutRoot.ActualHeight;
Loop counter, will loop 3 times
    int loopCount = 3;
Create a reference to our loop method
    Action loop = null;
Now when we run the loop we have a reference to the loop inside the loop function
    double delay = 0;
    double time = .6;
    PercentHandler ease = AnimationTransitions.CubicEaseOut;

    loop = () =>
    {
        EaseObject o = ball.SlideTo(rX(), rY(), time, ease, delay);
        loopCount--;
        if (loopCount >= 0 && loop != null) o.OnComplete((easeObject, percent) => loop());
    };
Start the loop
  loop();