CATransform3D perspective not working on CATransformLayer - ios

Note : Please ignore colors, gradients and size! My concern is perspective is not worked as expected
I am trying to achieve output as bellow,
But when I run my code it is giving me following output
Have a look at my code please :
CATransformLayer *baseLayer = [CATransformLayer layer];
baseLayer.anchorPoint = CGPointZero;
baseLayer.bounds = self.view.bounds;
baseLayer.position = CGPointMake(CGRectGetMidX(self.view.bounds), CGRectGetMidY(self.view.bounds));
[self.view.layer addSublayer:baseLayer];
CALayer *redLayer = [CALayer layer];
redLayer.backgroundColor = [UIColor redColor].CGColor;
redLayer.frame = CGRectMake(0, 0, 100, 100);
redLayer.position = CGPointMake(0,0);
redLayer.anchorPoint = CGPointMake(1, 0.5); // right
[baseLayer addSublayer:redLayer];
CALayer *blueLayer = [CALayer layer];
blueLayer.backgroundColor = [UIColor blueColor].CGColor;
blueLayer.bounds = CGRectMake(0, 0, 600, 100);
blueLayer.anchorPoint = CGPointMake(1, 0.5); // right
blueLayer.position = CGPointMake(-50,0);
[baseLayer addSublayer:blueLayer];
CATransform3D transform = CATransform3DIdentity;
transform.m34 = -1/80;
transform = CATransform3DRotate(transform, -M_PI_2, 0, 1, 0);
blueLayer.transform = transform;
baseLayer.sublayerTransform = CATransform3DRotate(CATransform3DIdentity, degreesToRadians(80), 0, 1, 0);

I Don't what makes this issue resolved but here is my updated code it is working as expected.
CATransformLayer *baseLayer = [CATransformLayer layer];
baseLayer.anchorPoint = CGPointZero;
baseLayer.bounds = self.view.bounds;
baseLayer.position = CGPointMake(CGRectGetMidX(self.view.bounds), CGRectGetMidY(self.view.bounds));
CALayer *redLayer = [CALayer layer];
redLayer.backgroundColor = [UIColor redColor].CGColor;
redLayer.frame = CGRectMake(0, 0, 1000, 250);
redLayer.position = CGPointMake(0,0);
redLayer.anchorPoint = CGPointMake(0, 0.5); // right
redLayer.transform = CATransform3DRotate(CATransform3DIdentity, M_PI_2,0.0f, 1.0f, 0.0f);
[baseLayer addSublayer:redLayer];
CALayer *blueLayer = [CALayer layer];
blueLayer.backgroundColor = [UIColor blueColor].CGColor;
blueLayer.bounds = CGRectMake(0, 0, 125, 250);
blueLayer.anchorPoint = CGPointMake(0, 0.5); // right
blueLayer.position = CGPointMake(0,0);
[baseLayer addSublayer:blueLayer];
CGFloat perspective = -1000.0; //This relates to the m34 perspective matrix.
CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity;
rotationAndPerspectiveTransform.m34 = 1.0 / perspective;
rotationAndPerspectiveTransform = CATransform3DRotate(newTransform, degreesToRadians(10) , 0.0f, 1.0f, 0.0f);
baseLayer.sublayerTransform = rotationAndPerspectiveTransform;

Related

Change perspective angle from right to left, in CATransformLayer iOS using CATransform3D

I am trying to draw one 3d block!
Using 2 layers and it is looking good in 3d for right side. see the attached image.
When I am trying to reuse same code for minor modification for left side! it's looking weird. See the attached image bellow,
I feel we can improve if we can change perspective angle, but don't know how to achieve that.
using transform.m34 for perspective. any help would be greatly appreciated.
Here is source code I am using.
// left Bar
/*{
CGFloat aViewWidth = 1000;
CAGradientLayer *blueLayer = [CAGradientLayer layer];
blueLayer.anchorPoint = P(0,0.5);
blueLayer.colors = #[
(id)aBarColor.CGColor,
(id)[UIColor blackColor].CGColor
];
blueLayer.startPoint = CGPointMake(0.0, 0.5);
blueLayer.endPoint = CGPointMake(1.5, 0.5);
blueLayer.frame = CGRectMake(125, 0, aViewWidth, 250);
blueLayer.transform = CATransform3DRotate(CATransform3DIdentity, M_PI_2, 0.0f, 1.0f, 0.0f);
[baseLayer addSublayer:blueLayer];
CAGradientLayer *redLayer = [CAGradientLayer layer];
redLayer.colors = #[
(id)[UIColor whiteColor].CGColor,
(id)aBarColor.CGColor
];
redLayer.startPoint = CGPointMake(-10.0, 0.5);
redLayer.endPoint = CGPointMake(1.0, 0.5);
redLayer.anchorPoint = P(0.5,0.5);
redLayer.frame = CGRectMake(0, 0, 125, 250);
[baseLayer addSublayer:redLayer];
CGFloat perspective = -1000; //This relates to the m34 perspective matrix.
CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity;
rotationAndPerspectiveTransform.m34 = 1.0 / perspective;
rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, degreesToRadians(-10.0) , 0.0f, 1.0f, 0.0f);
baseLayer.sublayerTransform = rotationAndPerspectiveTransform;
[self.view.layer addSublayer:baseLayer];
return;
CABasicAnimation *transformAnimation = [CABasicAnimation animationWithKeyPath: #"sublayerTransform"];
transformAnimation.fillMode = kCAFillModeForwards;
transformAnimation.removedOnCompletion = NO;
{
CGFloat w0 = 0;
CGFloat w1 = aViewWidth;
w0 = w0 * sin(degreesToRadians(10)) - perspective * cos(degreesToRadians(10));
w1 = w1 * sin(degreesToRadians(10)) - perspective * cos(degreesToRadians(10));
CGFloat newWidth = w1 - w0;
newWidth = newWidth * 1.2;
CATransform3D newTransform = CATransform3DIdentity;
newTransform.m34 = 1.0 / perspective;
newTransform = CATransform3DRotate(newTransform, degreesToRadians(-10) , 0.0f, 1.0f, 0.0f);
newTransform = CATransform3DScale(newTransform, 1.0f, 1.0f, 1.0f);
newTransform = CATransform3DTranslate(newTransform, newWidth, 0.0f, 0.0f);
transformAnimation.toValue = [NSValue valueWithCATransform3D:newTransform];
transformAnimation.duration = 10.0;
}
[baseLayer addAnimation:transformAnimation forKey:#"transform"];
}*/
// Right Bar
{
CGFloat aViewWidth = 1000;
CAGradientLayer *redLayer = [CAGradientLayer layer];
redLayer.colors = #[
(id)aBarColor.CGColor,
(id)[UIColor blackColor].CGColor
];
redLayer.startPoint = CGPointMake(0.0, 0.5);
redLayer.endPoint = CGPointMake(1.5, 0.5);
redLayer.frame = CGRectMake(0, 0, aViewWidth, 250);
redLayer.position = CGPointMake(0,0);
redLayer.anchorPoint = CGPointMake(0, 0.5); // right
redLayer.transform = CATransform3DRotate(CATransform3DIdentity, M_PI_2,0.0f, 1.0f, 0.0f);
[baseLayer addSublayer:redLayer];
CAGradientLayer *blueLayer = [CAGradientLayer layer];
blueLayer.colors = #[
(id)[UIColor whiteColor].CGColor,
(id)aBarColor.CGColor
];
blueLayer.startPoint = CGPointMake(-10.0, 0.5);
blueLayer.endPoint = CGPointMake(1.0, 0.5);
blueLayer.frame = CGRectMake(0, 0, 125, 250);
blueLayer.anchorPoint = CGPointMake(0, 0.5); // right
blueLayer.position = CGPointMake(0,0);
[baseLayer addSublayer:blueLayer];
CGFloat perspective = -1 * aViewWidth; //This relates to the m34 perspective matrix.
CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity;
rotationAndPerspectiveTransform.m34 = 1.0 / perspective;
rotationAndPerspectiveTransform = CATransform3DScale(rotationAndPerspectiveTransform, 0.1f, 0.1f, 0.1f);
baseLayer.sublayerTransform = rotationAndPerspectiveTransform;
[self.view.layer addSublayer:baseLayer];
CABasicAnimation *transformAnimation = [CABasicAnimation animationWithKeyPath: #"sublayerTransform"];
transformAnimation.fillMode = kCAFillModeForwards;
transformAnimation.removedOnCompletion = NO;
{
CGFloat w0 = 0;
CGFloat w1 = aViewWidth;
w0 = w0 * sin(degreesToRadians(10)) - perspective * cos(degreesToRadians(10));
w1 = w1 * sin(degreesToRadians(10)) - perspective * cos(degreesToRadians(10));
CGFloat newWidth = w1 - w0;
newWidth = newWidth * 1.225;
CATransform3D newTransform = CATransform3DIdentity;
newTransform.m34 = 1.0 / perspective;
newTransform = CATransform3DRotate(newTransform, degreesToRadians(10) , 0.0f, 1.0f, 0.0f);
newTransform = CATransform3DScale(newTransform, 1.0f, 1.0f, 1.0f);
newTransform = CATransform3DTranslate(newTransform, newWidth, 0.0f, 0.0f);
transformAnimation.toValue = [NSValue valueWithCATransform3D:newTransform];
transformAnimation.duration = 10.0;
}
[baseLayer addAnimation:transformAnimation forKey:#"transform"];
}
here is the working code :
// left Bar
{
CGFloat aViewWidth = 1000;
CAGradientLayer *blueLayer = [CAGradientLayer layer];
blueLayer.anchorPoint = P(0,0.5);
blueLayer.colors = #[
(id)aBarColor.CGColor,
(id)[UIColor blackColor].CGColor
];
blueLayer.startPoint = CGPointMake(0.0, 0.5);
blueLayer.endPoint = CGPointMake(1.5, 0.5);
blueLayer.frame = CGRectMake(125, 0, aViewWidth, 250);
blueLayer.transform = CATransform3DRotate(CATransform3DIdentity, M_PI_2, 0.0f, 1.0f, 0.0f);
[baseLayer addSublayer:blueLayer];
CAGradientLayer *redLayer = [CAGradientLayer layer];
redLayer.colors = #[
(id)[UIColor whiteColor].CGColor,
(id)aBarColor.CGColor
];
redLayer.startPoint = CGPointMake(-10.0, 0.5);
redLayer.endPoint = CGPointMake(1.0, 0.5);
redLayer.anchorPoint = P(1.0,0.5);
redLayer.frame = CGRectMake(0, 0, 125, 250);
[baseLayer addSublayer:redLayer];
CGFloat perspective = -1000; //This relates to the m34 perspective matrix.
CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity;
rotationAndPerspectiveTransform.m34 = 1.0 / perspective;
rotationAndPerspectiveTransform = CATransform3DScale(rotationAndPerspectiveTransform, 0.1f, 0.1f, 0.1f);
baseLayer.sublayerTransform = rotationAndPerspectiveTransform;
[self.view.layer addSublayer:baseLayer];
CABasicAnimation *transformAnimation = [CABasicAnimation animationWithKeyPath: #"sublayerTransform"];
transformAnimation.fillMode = kCAFillModeForwards;
transformAnimation.removedOnCompletion = NO;
{
CGFloat w0 = 0;
CGFloat w1 = aViewWidth;
w0 = w0 * sin(degreesToRadians(-10)) - perspective * cos(degreesToRadians(-10));
w1 = w1 * sin(degreesToRadians(-10)) - perspective * cos(degreesToRadians(-10));
CGFloat newWidth = w1 - w0;
newWidth = newWidth * 1.2;
CATransform3D newTransform = CATransform3DIdentity;
newTransform.m34 = 1.0 / perspective;
newTransform = CATransform3DRotate(newTransform, degreesToRadians(-10) , 0.0f, 1.0f, 0.0f);
newTransform = CATransform3DScale(newTransform, 1.0f, 1.0f, 1.0f);
newTransform = CATransform3DTranslate(newTransform, newWidth, 0.0f, 0.0f);
transformAnimation.toValue = [NSValue valueWithCATransform3D:newTransform];
transformAnimation.duration = 10.0;
}
[baseLayer addAnimation:transformAnimation forKey:#"transform"];
}
Change your redLayer ancherPoint to (1.0, 0.5) and use negative value of angle in w0 and w1. newWidth (which is used for translation) variable should be negative value for left side animation and positive value for right side animation.

How can I make the line turn?

I drew the line that turn like clock.
This is the line's moving of my ideal
but my code moves like this
How can I make a line like the second picture's line?
Here is my code
LineLayer.m
- (void)drawInContext:(CGContextRef)ctx
{
CGMutablePathRef path = CGPathCreateMutable();
CGPoint points[] = {
CGPointMake(160, 220),
CGPointMake(160, 120),
};
int numPoints = sizeof(points)/sizeof(points[0]);
CGPathAddLines(path, NULL, points, numPoints);
CGContextAddPath(ctx, path);
CGPathRelease(path);
UIColor *lineColor = [UIColor colorWithWhite:1.0 alpha:1.0];
CGContextSetStrokeColorWithColor(ctx, lineColor.CGColor);
CGContextSetLineWidth(ctx, 5.0);
CGContextDrawPath(ctx, kCGPathStroke);
}
ViewController.h
- (void)setup
{
LineLayer *linelayer = [LineLayer layer];
linelayer.frame = CGRectInset(self.view.bounds,0.0,0.0);
linelayer.anchorPoint = CGPointMake(0.5, 0.5);
[self.view.layer addSublayer:linelayer];
[linelayer setNeedsDisplay];
CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:#"transform.rotation"];
animation.toValue = [NSNumber numberWithFloat:M_PI / 2.0];
animation.duration = 0.5;
animation.repeatCount = MAXFLOAT;
animation.cumulative = YES;
[linelayer addAnimation:animation forKey:#"ImageViewRotation"];
}
you need a clock seconds needle or something like that??
#define DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI)
NSTimer *timer1;//global declaration
CALayer *layerLine;//global declaration
in viewDidLoad()
layerLine = [CALayer layer];
[layerLine setFrame:CGRectMake(0, 0,2, 90)];
[layerLine setBackgroundColor:[UIColor yellowColor].CGColor];
[self.view.layer addSublayer:layerLine];
CGPoint centerPoint = CGPointMake([[UIScreen mainScreen] bounds].size.width/2, ([[UIScreen mainScreen] bounds].size.height/2)-(layerLine.frame.size.height/4));
layerLine.anchorPoint = CGPointMake(0, 0);
layerLine.position = centerPoint;
layerLine.transform = CATransform3DMakeRotation(M_PI_2*2, 0.0, 0.0, 1.0);
if (!timer)
{
timer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:#selector(onTickTick) userInfo:nil repeats:YES];
}
timer invoking method
-(void)onTickTick
{
static int i = 180;
if (i==540)//if u change the value for i, it may affect this condition
{
i=180;
}
i=i+6;//u can replace 6 with 30 or any other value as u require
layerLine.transform = CATransform3DMakeRotation(DEGREES_TO_RADIANS(i), 0.0, 0.0, 1);
}

Scale a circle at same center position

I am working on scaling the circle and keep the same center position, which looks like the pulsing circle on map.
AnimationView.m
#property (nonatomic, strong) UIBezierPath *ovalPath;
- (void)drawCircle
{
UIGraphicsBeginImageContext(self.frame.size);
CGRect rect = CGRectMake(25.45, 49.25, 5.8, 5.8);
self.ovalPath = [UIBezierPath bezierPathWithOvalInRect: rect];
[self.ovalPath fill];
UIGraphicsEndImageContext();
}
- (void)bumpUpCircle
{
CAShapeLayer *pathLayer = [CAShapeLayer layer];
pathLayer.frame = self.bounds;
pathLayer.path = self.ovalPath.CGPath;
pathLayer.fillColor = [UIColor blackColor].CGColor;
pathLayer.lineWidth = 2.0f;
pathLayer.lineJoin = kCALineJoinBevel;
[self.layer addSublayer:pathLayer];
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"transform.scale"];
animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.0, 0.0, 0)];
animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(10.0, 10.0, 10.0)];
animation.repeatCount = 1;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
animation.duration = 1;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
[pathLayer addAnimation:animation forKey:#"transform.scale"];
NSLog(#"%#",NSStringFromCGPoint(self.bounds.origin));
}
However, the scaling position is in a strange position, rather than the center of the circle.
Any ideas will be very appreciated. Thanks.
Edit:
GIF uploaded
My suggestion for you with a pulsing circle, is to use an UIView and add it as a subview in your UIViewController. In following example you get a pulsing circle (a UIView with a cornerRadius like the radius) scaling up and down in a very few lines. Include this e.g. in your UIViewController's viewDidLoad to try it out.
int radius = 100;
UIView * circleView = [[UIView alloc] init];
circleView.backgroundColor = [UIColor greenColor];
circleView.frame = CGRectMake(0, 0, radius*2, radius*2);
circleView.center = self.view.center;
circleView.layer.cornerRadius = radius;
[self.view addSubview:circleView];
[UIView animateWithDuration:0.8f
delay:0.0f
options:UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat
animations:^{
circleView.transform = CGAffineTransformMakeScale(1.1, 1.1);
} completion:^(BOOL fin) {
// Do nothing
}];

Potential leak of an object stored into 'imageCrop'

This code running fine but when analyse, it shows potential memory leaks. It seems that imageCrop has potential memory leak. Your help is highly appreciated.
Here is my code.
-(CATransformLayer *)transformLayerFromImage:(UIImage *)image Frame:(CGRect)frame Duration:(CGFloat)duration AnchorPiont:(CGPoint)anchorPoint StartAngle:(double)start EndAngle:(double)end
{
CATransformLayer *jointLayer = [CATransformLayer layer];
jointLayer.anchorPoint = anchorPoint;
CALayer *imageLayer = [CALayer layer];
CAGradientLayer *shadowLayer = [CAGradientLayer layer];
double shadowAniOpacity;
if (anchorPoint.y == 0.5) {
CGFloat layerWidth;
if (anchorPoint.x == 0 ) //from left to right
{
layerWidth = image.size.width - frame.origin.x;
jointLayer.frame = CGRectMake(0, 0, layerWidth, frame.size.height);
if (frame.origin.x) {
jointLayer.position = CGPointMake(frame.size.width, frame.size.height/2);
}
else {
jointLayer.position = CGPointMake(0, frame.size.height/2);
}
}
else { //from right to left
layerWidth = frame.origin.x + frame.size.width;
jointLayer.frame = CGRectMake(0, 0, layerWidth, frame.size.height);
jointLayer.position = CGPointMake(layerWidth, frame.size.height/2);
}
//map image onto transform layer
imageLayer.frame = CGRectMake(0, 0, frame.size.width, frame.size.height);
imageLayer.anchorPoint = anchorPoint;
imageLayer.position = CGPointMake(layerWidth*anchorPoint.x, frame.size.height/2);
[jointLayer addSublayer:imageLayer];
CGImageRef imageCrop = CGImageCreateWithImageInRect(image.CGImage, frame);
imageLayer.contents = (__bridge id)imageCrop;
imageLayer.backgroundColor = [UIColor clearColor].CGColor;
//add shadow
NSInteger index = frame.origin.x/frame.size.width;
shadowLayer.frame = imageLayer.bounds;
shadowLayer.backgroundColor = [UIColor darkGrayColor].CGColor;
shadowLayer.opacity = 0.0;
shadowLayer.colors = [NSArray arrayWithObjects:(id)[UIColor blackColor].CGColor, (id)[UIColor clearColor].CGColor, nil];
if (index%2) {
shadowLayer.startPoint = CGPointMake(0, 0.5);
shadowLayer.endPoint = CGPointMake(1, 0.5);
shadowAniOpacity = (anchorPoint.x)?0.24:0.32;
}
else {
shadowLayer.startPoint = CGPointMake(1, 0.5);
shadowLayer.endPoint = CGPointMake(0, 0.5);
shadowAniOpacity = (anchorPoint.x)?0.32:0.24;
}
}
else{
CGFloat layerHeight;
if (anchorPoint.y == 0 ) //from top
{
layerHeight = image.size.height - frame.origin.y;
jointLayer.frame = CGRectMake(0, 0, frame.size.width, layerHeight);
if (frame.origin.y) {
jointLayer.position = CGPointMake(frame.size.width/2, frame.size.height);
}
else {
jointLayer.position = CGPointMake(frame.size.width/2, 0);
}
}
else { //from bottom
layerHeight = frame.origin.y + frame.size.height;
jointLayer.frame = CGRectMake(0, 0, frame.size.width, layerHeight);
jointLayer.position = CGPointMake(frame.size.width/2, layerHeight);
}
//map image onto transform layer
imageLayer.frame = CGRectMake(0, 0, frame.size.width, frame.size.height);
imageLayer.anchorPoint = anchorPoint;
imageLayer.position = CGPointMake(frame.size.width/2, layerHeight*anchorPoint.y);
[jointLayer addSublayer:imageLayer];
CGImageRef imageCrop = CGImageCreateWithImageInRect(image.CGImage, frame);
imageLayer.contents = (__bridge id)imageCrop;
imageLayer.backgroundColor = [UIColor clearColor].CGColor;
//add shadow
NSInteger index = frame.origin.y/frame.size.height;
shadowLayer.frame = imageLayer.bounds;
shadowLayer.backgroundColor = [UIColor darkGrayColor].CGColor;
shadowLayer.opacity = 0.0;
shadowLayer.colors = [NSArray arrayWithObjects:(id)[UIColor blackColor].CGColor, (id)[UIColor clearColor].CGColor, nil];
if (index%2) {
shadowLayer.startPoint = CGPointMake(0.5, 0);
shadowLayer.endPoint = CGPointMake(0.5, 1);
shadowAniOpacity = (anchorPoint.x)?0.24:0.32;
}
else {
shadowLayer.startPoint = CGPointMake(0.5, 1);
shadowLayer.endPoint = CGPointMake(0.5, 0);
shadowAniOpacity = (anchorPoint.x)?0.32:0.24;
}
}
[imageLayer addSublayer:shadowLayer];
//animate open/close animation
CABasicAnimation* animation = (anchorPoint.y == 0.5)?[CABasicAnimation animationWithKeyPath:#"transform.rotation.y"]:[CABasicAnimation animationWithKeyPath:#"transform.rotation.x"];
[animation setDuration:duration];
[animation setFromValue:[NSNumber numberWithDouble:start]];
[animation setToValue:[NSNumber numberWithDouble:end]];
[animation setRemovedOnCompletion:NO];
[jointLayer addAnimation:animation forKey:#"jointAnimation"];
//animate shadow opacity
animation = [CABasicAnimation animationWithKeyPath:#"opacity"];
[animation setDuration:duration];
[animation setFromValue:[NSNumber numberWithDouble:(start)?shadowAniOpacity:0]];
[animation setToValue:[NSNumber numberWithDouble:(start)?0:shadowAniOpacity]];
[animation setRemovedOnCompletion:NO];
[shadowLayer addAnimation:animation forKey:nil];
return jointLayer;
}
Whatever you create with CGImageCreateWithImageInRect should be released as this is a function from unmanaged memory land.
Use CGImageRelease to release the reference to unmanaged object:
CGImageRelease(imageCrop);
imageCrop = NULL;
OR
Use __bridge_transfer instead of __bridge to transfer object ownership over CGImageRef to ARC.
imageLayer.contents = (__bridge_transfer id)imageCrop;
In that case ARC will efficiently do #1 for you.
Good reads:
There is a great post on bridging in Objective-C: https://stackoverflow.com/a/17256947/351305
And related question: Does ARC work with Core Graphics objects?

How to put 2 layers to follow same bezierpath without one hiding the other

I have created 2 CALayers of same size and am passing these to the method below. However, the two layers runs together. How can I seperate these so that both are visible?
- (void) myAnimation : (CALayer *) sublayer {
UIBezierPath* aPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(30, 100, 270, 270)];
CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:#"position"];
anim.path = aPath.CGPath;
anim.rotationMode = kCAAnimationRotateAuto;
anim.repeatCount = HUGE_VALF;
anim.duration =35.0;
[sublayer addAnimation:anim forKey:#"race"];
}
Your path begins and ends at the same point. Assuming both beginning times are the same and duration is the same, your layers will precisely overlap. You can either shift the beginning time or rotate your UIBezierPath* aPath Here's an example of rotating your UIBezierPath* aPath and altering the duration. It should give you an idea how you could alter duration, begin time, rotation, etc.
- (void)viewDidLoad
{
[super viewDidLoad];
[self.view setBackgroundColor:[UIColor blackColor]];
CALayer * layer1 = [CALayer layer];
CALayer * layer2 = [CALayer layer];
[layer1 setFrame:CGRectMake(0, 0, 5, 50)];
[layer2 setFrame:CGRectMake(0, 0, 5, 100)];
layer1.backgroundColor = [[UIColor colorWithRed:.1 green:.5 blue:1 alpha:.35] CGColor];
layer2.backgroundColor = [[UIColor colorWithRed:.9 green:.2 blue:.5 alpha:.35] CGColor];
[self.view.layer addSublayer:layer1];
[self.view.layer addSublayer:layer2];
[self myAnimation:layer1 andRotation:0 andDuration:35.0];
[self myAnimation:layer2 andRotation:10 andDuration:10.0];
}
- (void) myAnimation:(CALayer *)sublayer andRotation:(CGFloat)rot andDuration:(CFTimeInterval)dur {
CGRect rect = CGRectMake(30, 100, 270, 270);
UIBezierPath* aPath = [UIBezierPath bezierPathWithOvalInRect:rect];
// Creating a center point around which we will transform the path
CGPoint center = CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect));
CGAffineTransform transform = CGAffineTransformIdentity;
transform = CGAffineTransformTranslate(transform, center.x, center.y);
transform = CGAffineTransformRotate(transform, rot);
// Recenter the transform
transform = CGAffineTransformTranslate(transform, -center.x, -center.y);
// This is the new path we will use.
CGPathRef rotated = CGPathCreateCopyByTransformingPath(aPath.CGPath, &transform);
CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:#"position"];
anim.path = rotated;
anim.rotationMode = kCAAnimationRotateAuto;
anim.repeatCount = HUGE_VALF;
anim.duration =dur;
[sublayer addAnimation:anim forKey:#"race"];
}

Resources