Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Layer Position jumps at start of (Core) Animation

So, I'm trying to create a tile flipping effect, like on Windows Phone 7.

So far I have the following code, but I have a couple of queries.

CALayer *layer = self.theRedSquare.layer;
CATransform3D initialTransform = self.theRedSquare.layer.transform;
initialTransform.m34 = 1.0 / -1000;

[UIView beginAnimations:@"Scale" context:nil];
[UIView setAnimationDuration:1];
[UIView setAnimationCurve: UIViewAnimationCurveEaseInOut];
layer.transform = initialTransform;
layer.anchorPoint = CGPointMake(-0.3, 0.5);

CATransform3D rotationAndPerspectiveTransform = self.theRedSquare.layer.transform;

rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, M_PI , 0 , -self.theRedSquare.bounds.size.height/2, 0);

layer.transform = rotationAndPerspectiveTransform;

[UIView setAnimationDelegate:self];
[UIView commitAnimations];

1. How come my my red square (a simple UI view) translates to the right at the start of the animation?

2. For the anchor point is it possible to set a position on the parent view? At the moment I am arbitrarily setting it relative to the current view.

Thanks in advance for any pointers.

Before animation

Before

During animation (notice the square has shifted right)

During

After animation (notice the square has shifted right)

After

Video added: example video

like image 484
JonB Avatar asked Feb 07 '12 20:02

JonB


Video Answer


3 Answers

-(void)setAnchorPoint:(CGPoint)anchorPoint forView:(UIView *)view
{
    CGPoint newPoint = CGPointMake(view.bounds.size.width * anchorPoint.x, view.bounds.size.height * anchorPoint.y);
    CGPoint oldPoint = CGPointMake(view.bounds.size.width * view.layer.anchorPoint.x, view.bounds.size.height * view.layer.anchorPoint.y);

    newPoint = CGPointApplyAffineTransform(newPoint, view.transform);
    oldPoint = CGPointApplyAffineTransform(oldPoint, view.transform);

    CGPoint position = view.layer.position;

    position.x -= oldPoint.x;
    position.x += newPoint.x;

    position.y -= oldPoint.y;
    position.y += newPoint.y;

    view.layer.position = position;
    view.layer.anchorPoint = anchorPoint;
}

-(void)animateView:(UIView *)theRedSquare
{
    CALayer *layer = theRedSquare.layer;
    CATransform3D initialTransform = theRedSquare.layer.transform;
    initialTransform.m34 = 1.0 / -1000;

    [self setAnchorPoint:CGPointMake(-0.3, 0.5) forView:theRedSquare];


    [UIView beginAnimations:@"Scale" context:nil];
    [UIView setAnimationDuration:1];
    [UIView setAnimationCurve: UIViewAnimationCurveEaseInOut];
    layer.transform = initialTransform;


    CATransform3D rotationAndPerspectiveTransform = theRedSquare.layer.transform;

    rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, M_PI , 0 , -theRedSquare.bounds.size.height/2, 0);

    layer.transform = rotationAndPerspectiveTransform;

    [UIView setAnimationDelegate:self];
    [UIView commitAnimations];
}

Taken from This, and slightly tweaked.. Hopefully it helps Changing my CALayer's anchorPoint moves the view

like image 78
vibrazy Avatar answered Oct 23 '22 16:10

vibrazy


If you make the square its own view, flipping is built-in

[UIView beginAnimations:@"flip" context:nil];
[UIView setAnimationDuration:.35f];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
[UIView setAnimationTransition: UIViewAnimationTransitionFlipFromLeft
     forView:self.window cache:YES];

// change to the new view (make this one hidden, the other not)

[UIView commitAnimations];
like image 32
Lou Franco Avatar answered Oct 23 '22 17:10

Lou Franco


The acceptable range of the anchorPoint of a CALayer is [0,1]. In your case, where you are attempting to flip around the Y axis, your layer's anchor point should be [0, 0.5].

like image 2
Mark Adams Avatar answered Oct 23 '22 18:10

Mark Adams