Posts Tagged ‘CAConstraint’

Core Animation CAConstraint Grid-Cell Layout

Tuesday, February 3rd, 2009

I really wanted to get a nice Grid Layout using CAConstraint, but I found the situation getting very complex very fast as each Cell needed to be able to reference the location of the last Cell and whether or not the Cell needed to drop down to a new Row, and at times needed to also reference the @”superlayer”. There has to be a better way, right?

CAConstraint Grid-Cell Layout with Animations

After a little digging around I was able to find an amazing Hot Chocolate blog post which showed a fantastic trick when laying out the Cells without having to reference the prior Cell. This approach takes advantage of knowing the Cell Row/Column position plus using the Scale: attribute of the CAConstraint on the @”superlayer” and it works like a charm.

[CAConstraint constraintWithAttribute: kCAConstraintWidth
relativeTo: @"superlayer"
attribute: kCAConstraintWidth
scale: 1.0 / columns
offset: 0]];

Want to change the number of Cells in the Grid? Modify these variables in this method:

- (void)layoutCellsInGridLayer:(CALayer *)layer {
	int columns = 6;
	int rows = 6;...

Also to give the project a little bit of “wow” here’s some random Y rotation on a Cell Layer:

- (void)setupFlipAnimationOnLayer:(CALayer *)layer {
	float duration = (float)frandom(0.5, 5.0);
 
	CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.y"];
	animation.fromValue = [NSNumber numberWithDouble:-1.0f * M_PI];
	animation.toValue = [NSNumber numberWithDouble:1.0f * M_PI];
	animation.duration = duration;
	animation.repeatCount = 1e100f;
	animation.beginTime = CACurrentMediaTime() + frandom(0.1, 30);
	animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
 
	[layer addAnimation:animation forKey:@"rotationY"];
}

To get the nice 3D perspective look the project needs the following code:

- (void)setupPerspectiveWithX:(float)x andY:(float)y {
	CATransform3D transform = CATransform3DMakeRotation(x, 0, 1, 0);
	transform = CATransform3DRotate(transform, y, 1, 0, 0);
	float zDistance = -450;
	transform.m34 = 1.0 / -zDistance;
	gridLayer.sublayerTransform = transform;
}

And one last final note: take a look in createCellInParentLayer: and you will see layer.contents. If you can provide your own image the layer will automatically Fill (layer.contentsGravity = kCAGravityResizeAspectFill;) and Mask (layer.masksToBounds = YES;) to make it fit.

You can grab the code here or download the binary here (requires Leopard).

Why is CAConstraint not working?

Monday, February 2nd, 2009

So you’re having problems with CAConstraint? It seems like no matter what you do the Constraint isn’t being applied to the Sublayer? And you’re CALayers are appearing in weird positions? Or not appearing at all?

Well the answer for me is surprisingly simple (and embarrassing)

1
2
3
4
[sublayer addConstraint:
[CAConstraint constraintWithAttribute:kCAConstraintMidX 
relativeTo:@"superlayer"
attribute:kCAConstraintMidX]]

Now see that that @”superlayer”? Notice that it’s not a Uppercase “L” as I was using “superLayer” where upon Core Animation was unable to find the layer “superLayer” and therefore have nothing to do with the constraints.