CoreAnimation CALayer and CATextLayer combination

2.9k views Asked by At

I'am just playing around with CA lately. Now I am kind of stuck. This is the thing I want to animate: enter image description here

As for now I already got the circle animation working. I subclassed CALayer to make the animation. I really don't know where to go from here. Where do I have to add the sublayer of CATextLayer? How do I animate both at the same time so it looks like the text with its line is sticking at the circle end?

If you need some code or anything else let me know.

I would be really happy to get some help here :-)

Thanks a lot!

2

There are 2 answers

2
jin On BEST ANSWER

I was able to do what you are asking for below. Code is very rough, just spent a couple minutes on it, may have missed releases and what have you. You can simply swap the UILabel for a CATextLayer (used UILabel for brevity).

    CAShapeLayer* circle = [[CAShapeLayer alloc] init];
    CGMutablePathRef path = CGPathCreateMutable();
    CGRect textRect = CGRectMake(self.bounds.size.width/4, (self.bounds.size.height-self.bounds.size.width/2)/2, self.bounds.size.width/2, self.bounds.size.width/2);
    float midX = CGRectGetMidX(textRect);
    float midY = CGRectGetMidY(textRect);
    CGAffineTransform t = CGAffineTransformConcat(
                            CGAffineTransformConcat(
                                CGAffineTransformMakeTranslation(-midX, -midY), 
                                CGAffineTransformMakeRotation(-1.57079633/0.99)), 
                            CGAffineTransformMakeTranslation(midX, midY));
    CGPathAddEllipseInRect(path, &t, textRect);
    circle.path = path;
    circle.frame = self.bounds;
    circle.fillColor = [UIColor clearColor].CGColor;
    circle.strokeColor = [UIColor blackColor].CGColor;
    circle.lineWidth = 60.0f;
    [self.layer addSublayer:circle];

    CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
    animation.duration = 15.0f;
    animation.fromValue = [NSNumber numberWithFloat:0.0f];
    animation.toValue = [NSNumber numberWithFloat:1.0f];
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
    [circle addAnimation:animation forKey:@"strokeEnd"];

    [circle release];

    UILabel* label = [[UILabel alloc] init];
    label.text = @"Test Text";
    label.font = [UIFont systemFontOfSize:20.0f];
    label.center = CGPathGetCurrentPoint(path);
    label.transform = CGAffineTransformMakeRotation(1.57079633);
    [label sizeToFit];
    [self.layer addSublayer:label.layer];

    CAKeyframeAnimation* textAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    textAnimation.duration = 15.0f;
    textAnimation.path = path;
    textAnimation.rotationMode = kCAAnimationRotateAuto;
    textAnimation.calculationMode = kCAAnimationCubicPaced;
    textAnimation.removedOnCompletion = NO;
    [label.layer addAnimation:textAnimation forKey:@"position"];
1
Andy B On

I would suggest creating a new UIView class, and then use the method layoutSubviews.
For more on the UIView class, just have a look at the class reference. Just use something lie this in your main view:

myView = [[myView alloc] initWithFrame:CGRectMake(100,100,100,100)];
[self.view addSubview:myView];

And something like this for layoutSubviews:

- (void) layoutSubviews{
     [super layoutSubviews];

      mainLayer.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);

      CALayer *circle = [[[CALayer alloc] init] autorelease];
      //You have to set up the circle image and everything
      circle.position = mainLayer.position;
}

Of course, your will have to add the implementation for myView over in your .h, but otherwise everything else should work.

EDIT: Sorry, I forgot to add the text layer code into layoutSubview, but all you to do is create the layer and set its position to mainLayer.position;