开发者

Problems with creating a Ken-Burns Effect

I'm currently trying to create a Ken Burns effect on an UIImageView. It firstly should zoom-in (slowly) and after that, the didStopSelector of the Animation should call a method, which should zoom-out. The Problem is, that the first animation (zoom-in) is okay and works perfectly, as long as I don't add the didStopSelector to the animation. If I do so, it seems like the method is called directly (not after it didStop).

Here are the 2 Methods which include the animations:

- (void)beginKenBurnsEffect {

    [UIView beginAnimations:@"a" context:self.view_image];
    [UIView setAnimationCurve:UIViewAnimationCurveLinear];
    [UIView setAnimationDuration:5];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDidStopSelector:@selector(endKenBurnsEffect)];
    [UIView setAnimationDelegate:self];


    self.view_image.transform = CG开发者_如何学CAffineTransformScale(self.view_image.transform, 1.06, 1.06);
    self.view_image.center = CGPointMake(self.frame.size.width/1.7, self.frame.size.height/2);

    [UIView commitAnimations];
}

- (void)endKenBurnsEffect {

    [UIView beginAnimations:@"b" context:self.view_image];
    [UIView setAnimationCurve:UIViewAnimationCurveLinear];
    [UIView setAnimationDuration:5];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDidStopSelector:@selector(beginKenBurnsEffect)];
    [UIView setAnimationDelegate:self];

    self.view_image.transform = self.origTransform;
    self.view_image.center = self.origPoint;

    [UIView commitAnimations];
}

After I initialized the UIImageView, I save the current Transform and Center values to a property.

self.origTransform = self.view_image.transform;
self.origPoint = self.view_image.center;

I also tried it with only one animation and setAnimationAutoReverse, but after the animation is done, it zooms-in without animation (after it did zoom-out slowly animated).

Maybe you have an idea what the problem could be.

Thank you in advance :)


Have you tried using a CAAnimationGroup and using a few CAAnimations?

NSMutableArray * animations = [ NSMutableArray array ] ;
{
    CAAnimation * anim = [ CABasicAnimation animationWithKeyPath:@"transform" ] ;
    anim.fromValue = [ NSValue valueWithCGAffineTransform:CGAffineTransformScale(...) ] ;
    [ array addObject:anim ] ;
}
{
    CAAnimation * anim = // make intro position transform
    [ array addObject:anim ] ;
}

{
    CAAnimation * anim = // make outro position transform for layer.transform
    anim.offset = 5.0;
}

{
    CAAnimation * anim = // make outro position transform for layer.position
    anim.offset = 5.0;
}

CAAnimationGroup * group = [ CAAnimationGroup animation ] ;
group.animations = animations ;

[ CATransaction begin ] ;
[ self.view.layer addAnimation:group forKey:nil ] ;
[ CATransaction commit ] ;

... this is just a rough draft


What happens if you call endKenBurnsEffect from your main thread?

i.e. change [UIView setAnimationDidStopSelector:@selector(endKenBurnsEffect)]; to `[UIView setAnimationDidStopSelector:@selector(invokeEndKenBurnsEffect)];'

where -(void)invokeEndKenBurnsEffect looks like:

-(void)invokeEndKenBurnsEffect
{
    [ self performSelectorOnMainThread:@selector( endKenBurnsEffect )
                            withObject:nil 
                         waitUntilDone:NO ] ;
}


You can still use block-based animation with recursion:

In your .h file

@interface YourClass : UIViewController{
    BOOL kenBurnsIsAnimating;
}

In your .m file

- (void)viewDidLoad{
   kenBurnsIsAnimating = YES;  
   [self kenBurns:YES];  
}

- (void)kenBurns:(BOOL)isOpening{
    if (kenBurnsIsAnimating) {
        [UIView animateWithDuration:5.0
                              delay:1.0
                            options:UIViewAnimationCurveEaseInOut
                         animations:^{
                             if (isOpening) {
                                 // do your opening animation (zoom in and panning)
                             }else{
                                 // do your closing animation (zoom out and panning)
                             }
                         }
                         completion:^(BOOL finished){
                             if (finished) {
                                 [self kenBurns:!isOpening];
                             }
                         }];
    }    
}

This way you will create transition with recursion and anything what you will do in animation block will be happening over and over again (thats why there is isOpening YES/NO value) until you wont set up kenBurnsIsAnimating as NO. But still, the current animation will have to finish.

For more information about block-based animation check out http://developer.apple.com/library/IOS/#documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/AnimatingViews/AnimatingViews.html#//apple_ref/doc/uid/TP40009503-CH6-SW4 There is also example for connecting two block based animation after each other. Listing 4-2.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜