Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Animate CALayer scale without blurring

I have a CALayer that implements drawInContext: and draws a simple circle, like so:

- (void)drawInContext:(CGContextRef)ctx
{
     CGContextScaleCTM(ctx, DrawingScale, DrawingScale);
     CGContextSetRGBFillColor (ctx, 1, 0, 0, 1);
     CGContextFillEllipseInRect (ctx, LocationRectangle);
}

I have been experimenting with different ways of increasing the size of my circle based on a touch event. I've tried using the UIView beginAnimation system and CABasicAnimation's, bbut they all blur the image. In my reading I have discovered that is because the CALayer's seem to be treated like bitmaps for these options.

Fair enough... but I want to scale my graphics without blurring, e.g. to use vector scaling.

As such, in my code I have a "DrawingScale" property.

Is there a neat way to scale this property using Layer animations? Or is this something people do with NSTimers (yuk)?

Might this be one situation where I can use Core Animation's ability to animate custom properties? If so, I'd love to know which example people find is the best, or which section of the Apple docs might be a good place to start with this topic.

It seems when it comes to graphics on Mac/iOS, there are many ways to skin/draw a cat...?

like image 545
Fuzz Avatar asked Mar 23 '26 11:03

Fuzz


1 Answers

After spending a few days working on this, one solution I have is to have a variable called "DrawingScale" as a member variable (is that what they are called in Obj-C) and using Core Animation to animate that property.

- (void)drawInContext:(CGContextRef)ctx
{
    CGFloat size = (CGFloat)(DrawingScale*DEFAULT_SIZE);
    CGRect elipseRect = CGRectMake(xPos, yPos, size, size);
    CGContextStrokeEllipseInRect(ctx, elipseRect);
    CGContextFillEllipseInRect (ctx, elipseRect);
}

Then on an event, I set up an animation as such:

-(void) : (CGPoint) location
{
    /* Set up an explicit animation to scale the players size up */
    CABasicAnimation* anim = [CABasicAnimation animationWithKeyPath:@"DrawingScale"];
    anim.fromValue = [NSNumber numberWithFloat: 1];
    anim.toValue = [NSNumber numberWithFloat: 5];
    anim.removedOnCompletion = YES;
    anim.duration = 0.1;
    anim.delegate = self;
    anim.fillMode = kCAFillModeForwards;
    anim.autoreverses = NO;
    [self addAnimation: anim forKey:@"ElipseGettingBigger"];
}

This sets up the animation to set my variable DrawingScale to range from 1 to 5, and do so within 0.1 of a second. It works really well.

I did need to be careful and make sure I had adjusted the layer bounds accordingly first too!

like image 68
Fuzz Avatar answered Mar 25 '26 02:03

Fuzz