使用Core Graphics和Core Animations创建包含圆圈的动画

时间:2012-02-27 01:13:19

标签: ios core-animation core-graphics

我正在尝试一些时间,但没有成功。 我制作了一些我想要的动画圈。它从半径23到半径7动画。

Shema

有一个代码工作正常,但没有透明的圆圈。

我需要帮助才能让这个“透明的内圈”在动画中运作。

一些 CustomLayer

@dynamic circleRadius; // Linked post tells us to let CA implement our accessors for us.
// Whether this is necessary or not is unclear to me and one 
// commenter on the linked post claims success only when using
// @synthesize for the animatable property.



+ (BOOL)needsDisplayForKey:(NSString*)key {
    // Let our layer know it has to redraw when circleRadius is changed
    if ([key isEqualToString:@"circleRadius"]) {
        return YES;
    } else {
        return [super needsDisplayForKey:key];
    }
}

- (void)drawInContext:(CGContextRef)ctx {

    // This call is probably unnecessary as super's implementation does nothing
    [super drawInContext:ctx];


    CGRect rect = CGContextGetClipBoundingBox(ctx);

    CGContextSetRGBFillColor(ctx, 1.000, 0.533, 0.000, 0.1);
    CGContextSetRGBStrokeColor(ctx, 1.000, 0.533, 0.000, 0.5);

    // Construct a CGMutablePath to draw the light blue circle
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathAddArc(path, NULL, rect.size.width / 2, 
                 rect.size.height / 2, 
                 self.circleRadius, 0, 2 * M_PI, NO);


    // Fill the circle
    CGContextAddPath(ctx, path);

    CGContextFillPath(ctx);

    // Stroke the circle's border
    CGContextAddPath(ctx, path);
    CGContextStrokePath(ctx);

    // Release the path
    CGPathRelease(path);

    CGContextStrokePath(ctx);

}

和mu UIView中某处的动画部分

CustomLayer *customLayer = [[CustomLayer alloc] init];

    if ([customLayer respondsToSelector:@selector(setContentsScale:)])
    {
        [customLayer setContentsScale:[[UIScreen mainScreen] scale]];
    }

    // Make layer big enough for the initial radius
    // EDIT: You may want to shrink the layer when it reacehes it's final size
    [customLayer setFrame:CGRectMake(0, 0, 57, 52)];
    [self.layer addSublayer:customLayer];


    CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"circleRadius"];
    animation.repeatCount = MAXFLOAT;
    // Zoom in, oscillate a couple times, zoom in further
    animation.values = [NSArray arrayWithObjects:[NSNumber numberWithFloat:23], 
                        [NSNumber numberWithFloat:22], 
                        [NSNumber numberWithFloat:20], 
                        [NSNumber numberWithFloat:18], 
                        [NSNumber numberWithFloat:15], 
                        [NSNumber numberWithFloat:13],
                        [NSNumber numberWithFloat:11],
                        [NSNumber numberWithFloat:9],
                        [NSNumber numberWithFloat:7], 
                        [NSNumber numberWithFloat:7],
                        [NSNumber numberWithFloat:7],
                        [NSNumber numberWithFloat:7],
                        nil];
    // We want the radii to be 20 in the end
    customLayer.circleRadius = 7;

    // Rather arbitrary values.  I thought the cubic pacing w/ a 2.5 second pacing
    // looked decent enough but you'd probably want to play with them to get a more
    // accurate imitation of the Maps app.  You could also define a keyTimes array for 
    // a more discrete control of the times per step.
    animation.duration = 1.5;
    animation.calculationMode = kCAAnimationCubicPaced;

    [customLayer addAnimation:animation forKey:nil];

1 个答案:

答案 0 :(得分:5)

对于你想要“甜甜圈”的情况,你需要建立如下图:

CGMutablePathRef path = CGPathCreateMutable();
CGPathAddArc(path, NULL, rect.size.width / 2, 
             rect.size.height / 2, 
             self.circleRadius, 0, 2 * M_PI, NO);
CGPathAddArc(path, NULL, rect.size.width / 2, 
             rect.size.height / 2, 
             self.circleRadius/2.0, 0, 2 * M_PI, NO);
CGContextAddPath(ctx, path);

CGContextSetRGBFillColor(ctx, 1.000, 0.533, 0.000, 0.1);
CGContextEOFillPath(ctx);  // Note - you want the even-odd fill rule to get the donut

CGPathRelease( path);

// now the outside stroke

CGContextBeginPath( ctx ); // removes previous path
path = CGPathCreateMutable();
CGPathAddArc(path, NULL, rect.size.width / 2, 
         rect.size.height / 2, 
         self.circleRadius, 0, 2 * M_PI, NO);

CGContextSetRGBStrokeColor(ctx, 1.000, 0.533, 0.000, 0.5);

CGContextAddPath(ctx, path);
CGContextStrokePath(ctx);

CGPathRelease( path)

对于你只想要描边外径的情况,就这样做。不要做路径填充。