cybermach
cybermach

Reputation: 125

How do we rotate 2 UIView planes simultaneously in 3D space

I'm trying to create a "page flip effect" using UIView instead of CALayer due to a project limitation. This requires flipping 1 UIView 180 degrees and essentially "sticking it" to the back of the other UIView. You then rotate the two UIViews simultaneously by rotating the superview in 3D space.

I'm trying to port AFKPageFlipper's "initFlip" method to use UIView instead of UIImage.

Below is a snippet of my attempt to port it. The initial page flip works, but the "front layer" in the code doesn't seem to show up. As if I"m not able to see the backend of the page. When I'm flipping the page, the animation is initially correct (back layer is fine), but then the other side of the page (front layer), I see the inverted view of the first page (backLayer).

Any help would be awesome!

flipAnimationLayer = [[UIView alloc] init];

flipAnimationLayer.layer.anchorPoint = CGPointMake(1.0, 0.5);
flipAnimationLayer.layer.frame = rect;

[self addSubview:flipAnimationLayer];

UIView *backLayer;
UIView *frontLayer;
if (flipDirection == AFKPageFlipperDirectionRight)
{
    backLayer = currentViewSnap2;
    backLayer.layer.contentsGravity = kCAGravityLeft;

    frontLayer = nextViewSnap2;
    frontLayer.layer.contentsGravity = kCAGravityRight;

}else
{
    backLayer = nextViewSnap2;
    backLayer.layer.contentsGravity = kCAGravityLeft;

    frontLayer= currentViewSnap2;
    frontLayer.layer.contentsGravity = kCAGravityRight;
}


backLayer.frame = flipAnimationLayer.bounds;
backLayer.layer.doubleSided = NO;
backLayer.clipsToBounds = YES;

[flipAnimationLayer addSubview:backLayer];


frontLayer.frame = flipAnimationLayer.bounds;
frontLayer.layer.doubleSided = NO;
frontLayer.clipsToBounds = YES;
frontLayer.layer.transform = CATransform3DMakeRotation(M_PI, 0, 1.0, 0);

[flipAnimationLayer addSubview:frontLayer];

if (flipDirection == AFKPageFlipperDirectionRight)
{
    CATransform3D transform = CATransform3DMakeRotation(0.0, 0.0, 1.0, 0.0);
    transform.m34 = 1.0f / 2500.0f;

    flipAnimationLayer.layer.transform = transform;

    currentAngle = startFlipAngle = 0;
    endFlipAngle = -M_PI;
} else
{


    CATransform3D transform = CATransform3DMakeRotation(-M_PI / 1.1, 0.0, 1.0, 0.0);
    transform.m34 = 1.0f / 2500.0f;

    flipAnimationLayer.layer.transform = transform;

    currentAngle = startFlipAngle = -M_PI;
    endFlipAngle = 0;
}

Upvotes: 0

Views: 597

Answers (1)

Duncan C
Duncan C

Reputation: 131436

Your code is rotating layers, not views. That's fine.

I would not expect the code you posted to animate, since a layer's backing view doesn't do implicit animation, You could make it animate by using a CABasicAnimation. Or, you could create layers for your front and back views and attach them as sublayers of your view's layers. If you do that than manipulating the transform on the layers will use implicit animations.

What I've done to create my own font-to-back flip as you describe is to fake it.

I animate in 2 steps: First from zero degrees (flat) to 90 degrees (where the layers become invisible.) At that moment I hide the first layer and make the second layer visible, rotated 90 degrees the other way, and then rotate the other layer back to zero. This creates the same visual effect as showing the back face of the rotation.

If you use implicit layer animation to do this you'll need to put the changes to the transform inside a CATransaction block and set the animation timing to linear, or use ease-in for the first half and ease-out for the second half. That's because animations default to ease-in,ease-out timing, and the first animation to 90 degrees will slow down at the end, and then the second 90 degree animation will ease in.

Upvotes: 1

Related Questions