Search code examples
iostransformationcatransform3d

Set layer.transform with CATransform3DRotate like UIViewAnimationOptionTransitionFlipFromRight


I've set up a view such that when the app navigates forward, it performs transitionFromView using the UIViewAnimationOptionTransitionFlipFromRight option. That yields an effect like:

Using UIViewAnimationOptionTransitionFlipFromRight

Navigating backwards uses UIViewAnimationOptionTransitionFlipFromLeft, but otherwise is the same. Ok, so far, so good.

Now, I've also set up a UIPanGestureRecognizer so that I can link the flipping of views with a user's horizontal gesture on the screen. But clearly I can't use transitionFromView in that case, so my gesture recognizer is manually setting the transform property of the layer with:

CATransform3D transform = CATransform3DIdentity;
transform.m34 = 1.0 / -800.0;
viewToTransform.layer.transform = CATransform3DRotate(transform, M_PI * rotationPercent, 0.0, 1.0, 0.0);

But this is yielding a subtly different effect:

CATransform3DRotate

In the UIViewAnimationOptionTransitionFlipFromRight option of transitionFromView the view is scaled during the flipping animation such that the tallest edge of the flipped view stays the height of the container view. But when manually doing the transform of the layer, it's the center of the view that stays a constant size, slightly cropping the corners of the longer edge of the flipped view during the animation.

How do I achieve this effect when setting the transform property of the layer in my gesture recognizer (I probably want to adjust my opacity, too, to get the slight dimming effect that the transitionFromView achieves). I'm thinking I could use CATransform3DMakeScale and manually calculate the scaling function based upon the angle of the rotation and my particular m34 setting, but before I go through that exercise, I want to make sure I'm not overlooking some more intuitive or natural way to achieve this simultaneous scaling and rotating that the standard flip animation entails. And even if I have to calculate the scaling factor manually, I'd appreciate guidance as to how to define that as a function of the m34 setting and the angle (I'm no expert in the subtleties of vector transformations).


Solution

  • The transforms are all based around your layers anchorPoint. That is the "pivot point" around which you rotate.

    The anchorPoint uses a scale from 0 to 1 in both x and y and defaults to 0.5, 0.5

    I believe you would want your anchor for your layer set like this:

    viewToTransform.layer.anchorPoint = CGPointMake(0.5, 1);
    

    There is some good info and research locations in the answers to this question:

    Changing my CALayer's anchorPoint moves the view