1

I want to 'queue' an animation sequence that would sequentially slide a series of labels out of view with a slight delay between each slide-out. Starting from the top one and ending in the last one. Currently I have the following function which I call on the tap of a button:

func slideLabelsOut(labelArguments: UILabel...) {

    var labelAnimation = POPDecayAnimation();
    labelAnimation.property = POPAnimatableProperty.propertyWithName(kPOPLayerPositionX) as POPAnimatableProperty;

    labelAnimation.velocity = -720;

    for label in labelArguments {
        var layer = label.layer;
        layer.pop_addAnimation(labelAnimation, forKey: "Slide");
    }

}

So... I tried using usleep() in the for loop, however as I found out it blocks the main thread which is absolutely useless to me... So is there any built in solution for this kind of thing within Pop? Or should I maybe use some other framework? Also... if there's not a built in solution how should I approach queuing animations in the future (I recon I'll be doing that a lot)?

Dima
  • 23,484
  • 6
  • 56
  • 83
Martin Velchevski
  • 874
  • 11
  • 33
  • 1
    You can utilize `dispatch_after` which is part of GCD. There should be a code snippet for it too. – Jack Jun 12 '14 at 21:27

2 Answers2

1

This answer is specific to the Facebook POP framework.

Every POP animation is a subclass of the POPAnimation class which has a beginTime property.

/**
 @abstract The beginTime of the animation in media time.
 @discussion Defaults to 0 and starts immediately.
 */
@property (assign, nonatomic) CFTimeInterval beginTime;

You can use that to stagger the start times of your animations.

Dima
  • 23,484
  • 6
  • 56
  • 83
0

I have a similar requirement. I'm animating a wind direction gauge as part of a weather app. As it replays the weather over the day the pointer on the gauge will move round the compass points - just like a wind vane would. I have this working in Objective C, as a queue which I added the successive animations to, then I play the animations from the queue. I also have a similar animation for a thermometer showing how the mercury level has risen and fallen through the day.

Basically I have a function getNextAnimation which gets an animation from the queue and runs it. When the animation completes, it calls getNextAnimation. So the animations chain onto each other. Once I've queued my animations, I call getNextAnimation to start the sequence.

I am porting this app to Swift and yesterday started to work on the animation. I think I'll use the same approach:

My queue and getNetxAnimation function:

typealias animationBlock = ()->Void
var animationBlocks:Array<animationBlock> = Array()
func getNextAnimation() -> animationBlock?
{
    var block:animationBlock?
    if animationBlocks.count > 0 { block = animationBlocks.removeAtIndex(0) }
    return block;
}

My animations are added using code like (the curves and the actual animation are specific to my app):

var aBlock:animationBlock = { () in
    UIView.animateWithDuration(self.secondsPerAnimation,
        delay: 0.0,
        options: UIViewAnimationOptions.CurveEaseInOut | UIViewAnimationOptions.BeginFromCurrentState,
        animations: {
            self.windDirectionPointer!.transform = CGAffineTransformMakeRotation(degreesToRadians(degrees))
        },
        completion: { (value: Bool) -> Void in
            var block:animationBlock? = getNextAnimation()
            if (block) { block!() }
        })
}
animationBlocks.append(aBlock)

I bootstrap the animations with:

getNextAnimation()!()  // This assumes that getNextAnimation doesn't return nil!
Derek Knight
  • 225
  • 2
  • 9