There is an open source reimplementation of this already.
This blog post: Mesh Transforms covers the private CAMeshTransform
. Rather than treating a CALayer as a simple quad, it allows CALayers to be turned into a mesh of connected faces. This class is how Apple has been able to implement the page curl and iBooks page turning effects.
However, the API doesn't tolerate malformed input at all well and Apple has kept it a private API.
If you keep reading that blog post though you'll come to this section just after the bit about it being private API.
In the spirit of CAMeshTransform I created a BCMeshTransform which copies almost every feature of the original class.
...
Without direct, public access to Core Animation render server I was forced to use OpenGL for my implementation. This is not a perfect solution as it introduces some drawbacks the original class didn’t have, but it seems to be the only currently available option.
In effect he renders the content view into an OpenGL texture and then displays that. This lets him mess around with it however he likes.
Including like this...
I encourage you to check out the demo app I made for BCMeshTransformView. It contains a few ideas of how a mesh transform can be used to enrich interaction, like my very simple, but functional take on that famous Dribbble.
What famous Dribbble? This one:
Here is what the example looks like:
Open source project: https://github.com/Ciechan/BCMeshTransformView
Example Implementation of the curtain effect: BCCurtainDemoViewController.m
How does it work?
It sets the BCMeshTransformView
up with some lighting and perspective.
// From: https://github.com/Ciechan/BCMeshTransformView/blob/master/Demo/BCMeshTransformViewDemo/BCCurtainDemoViewController.m#L59
self.transformView.diffuseLightFactor = 0.5;
CATransform3D perspective = CATransform3DIdentity;
perspective.m34 = -1.0/2000.0;
self.transformView.supplementaryTransform = perspective;
Then using a UIPanGestureRecognizer it tracks the touches and uses this method to build a new mesh transform every time the users finger moves.
// From: https://github.com/Ciechan/BCMeshTransformView/blob/master/Demo/BCMeshTransformViewDemo/BCCurtainDemoViewController.m#L91
self.transformView.meshTransform = [BCMutableMeshTransform curtainMeshTransformAtPoint:CGPointMake(point.x + self.surplus, point.y) boundsSize:self.transformView.bounds.size];
// From: https://github.com/Ciechan/BCMeshTransformView/blob/master/Demo/BCMeshTransformViewDemo/BCMeshTransform%2BDemoTransforms.m#L14
+ (instancetype)curtainMeshTransformAtPoint:(CGPoint)point boundsSize:(CGSize)boundsSize
{
const float Frills = 3;
point.x = MIN(point.x, boundsSize.width);
BCMutableMeshTransform *transform = [BCMutableMeshTransform identityMeshTransformWithNumberOfRows:20 numberOfColumns:50];
CGPoint np = CGPointMake(point.x/boundsSize.width, point.y/boundsSize.height);
[transform mapVerticesUsingBlock:^BCMeshVertex(BCMeshVertex vertex, NSUInteger vertexIndex) {
float dy = vertex.to.y - np.y;
float bend = 0.25f * (1.0f - expf(-dy * dy * 10.0f));
float x = vertex.to.x;
vertex.to.z = 0.1 + 0.1f * sin(-1.4f * cos(x * x * Frills * 2.0 * M_PI)) * (1.0 - np.x);
vertex.to.x = (vertex.to.x) * np.x + vertex.to.x * bend * (1.0 - np.x);
return vertex;
}];
return transform;
}