

以下のリンクを参考にし、円グラフを作成してます。<https://gist.github.com/glayash/38aa605f99a9666a925d>  
条件によってグラフの色を変えたいのですが、アニメーション中は変わりません。アニメーション時間に設定した時間が終わると、パッと変わります。一部コードを抜粋して以下に記しました。  
ViewControllerによりparamが100以下のときグラフを赤くしようとしております。

ViewController.m

[code]

    if( param < 100) {
    
        [_graph setfillColor:[UIColor redColor]];
    } else {
        [_graph setfillColor:[UIColor blueColor]];
    }
    
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"value"];
    
    animation.duration = 5;
    animation.repeatCount = 1;
    animation.fromValue = [NSNumber numberWithFloat:0.0];
    animation.toValue = [NSNumber numberWithFloat:per];
    
    animation.fillMode = kCAFillModeForwards;
    animation.removedOnCompletion = YES;
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    
    [_graph addAnimation:animation forKey:@"key"];入力
    
[/code]

AnimatableGraph.h

[code]

    @property (nonatomic) UIColor *fillColor;
    
[/code]

AnimatableGraph.m

[code]

    @implementation SKCircleGraphLayer{
    
        CGFloat red,green,blue,alpha;
    
    }    
    
    
    -(void)drawInContext:(CGContextRef)ctx{
    
    
        fillColor getRed:&red green:&green blue:&blue alpha:&alpha];
    
        NSLog(@"%f",red); //アニメーション中は0となり終了後1となる。
    
        CGContextSaveGState(ctx);
    
        CGFloat x = self.bounds.origin.x;
    
        x += self.bounds.size.width/2;
    
        CGFloat y = self.bounds.origin.y;
        y += self.bounds.size.height/2;
    
        CGContextSetLineWidth(ctx, 0);
    
        CGMutablePathRef path = CGPathCreateMutable();
    
        CGPathAddArc(path, NULL, x, y, x-10, 0, M_PI*2, NO);
        CGContextAddPath(ctx, path);
        CGContextSetRGBFillColor(ctx,0.6, 0.6, 0.6,1.0); //gray
    
        CGContextSetLineWidth(ctx, 0);
        CGContextDrawPath(ctx, kCGPathFillStroke);
    
        // 3時の方向が0度なので補正
        double start = -45;
    
        double aDegree = _degree - (180 - start);
    
        CGMutablePathRef graph = CGPathCreateMutable();
    
        CGPathAddArc(graph, nil, x, y,x-10,(M_PI * 2.0 * (start - 180) / 360),(M_PI * 2.0) * (aDegree / 360.0), false);
        CGPathAddLineToPoint(graph, nil, x, y);
        CGContextAddPath(ctx, graph);
        CGContextSetRGBFillColor(ctx, red,green, blue,alpha);    
    
        CGContextDrawPath(ctx, kCGPathFillStroke);
    
        CGContextRestoreGState(ctx);
    }
    
[/code]


CC BY-SA 3.0
2015-03-25T09:08:48.340
8375
2015-03-26T06:49:54.580
2015-03-25T09:23:39.447
7362
8060
question
ios objective-c cabasicanimation
CABasicAnimationでアニメーションをする図の色を変更する


いちおう、「動く」プログラムを作りました。しかし、それが質問者さんが求めているプログラムである保証はありません。  
ViewControllerにUIViewインスタンスgraphViewを貼り付け、それに円グラフを描画します。円グラフの描画は、CALayerのサブクラス、GraphLayerで行います。

ViewController.h ---------

[code]

    #import <UIKit/UIKit.h>
    // 変更なし。
    @interface ViewController : UIViewController
    
    @end
    
[/code]

ViewController.m --------

[code]

    #import "ViewController.h"
    #import "GraphLayer.h"
    
    @interface ViewController ()
    // Storyboardで、graphViewを貼り付け。いちおう正方形にすることを推奨。
    @property (weak, nonatomic) IBOutlet UIView *graphView;
    // GraphLayerのインスタンス。
    @property (nonatomic) GraphLayer *graphLayer;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        self.graphLayer = [[GraphLayer alloc] init];
        self.graphLayer.frame = CGRectMake(0.0, 0.0, self.graphView.frame.size.width, self.graphView.frame.size.height);
        // 円グラフの初期値は、40%。
        self.graphLayer.perCent = 40.0;
        // 円グラフの初期カラーは赤。色情報をHSBで扱う点に注目。
        UIColor *redColor = [UIColor redColor];
        CGFloat theHue;
        [redColor getHue: &theHue saturation: NULL brightness: NULL alpha: NULL];
        self.graphLayer.hue = theHue;
        [self.graphView.layer addSublayer: self.graphLayer];
    }
    // アニメーションを開始するアクションメソッド。
    - (IBAction)animate:(id)sender {
        CABasicAnimation *graphAnimation = [[CABasicAnimation alloc] init];
        graphAnimation.keyPath = @"perCent";
        graphAnimation.fromValue = [NSNumber numberWithFloat: 40.0];
        // 変更後90%とする。
        self.graphLayer.perCent = 90.0;
        graphAnimation.toValue = [NSNumber numberWithFloat: 90.0];
    
        CABasicAnimation *colorAnimation = [[CABasicAnimation alloc] init];
        // 変更後青色にする。
        colorAnimation.keyPath = @"hue";
        UIColor *redColor = [UIColor redColor];
        CGFloat redHue;
        [redColor getHue: &redHue saturation: NULL brightness: NULL alpha: NULL];
        colorAnimation.fromValue = [NSNumber numberWithFloat: redHue];
        UIColor *blueColor = [UIColor blueColor];
        CGFloat theHue;
        [blueColor getHue: &theHue saturation: NULL brightness: NULL alpha: NULL];
        self.graphLayer.hue = theHue;
        colorAnimation.toValue = [NSNumber numberWithFloat: theHue];
        // 複数のアニメーションを同時に行うには、CAAnimationGroupクラスを使う。
        CAAnimationGroup *group = [[CAAnimationGroup alloc] init];
        group.animations = @[graphAnimation, colorAnimation];
        group.duration = 1.0;
        [self.graphLayer addAnimation: group forKey: @"Graph"];
    }
    
    @end
    
[/code]

GraphicLayer.h --------

[code]

    #import <UIKit/UIKit.h>
    // Xcode 6、iOS 8.xでは、QuartzCoreフレームワークをインポートしなくてもいいらしい。
    #import <QuartzCore/QuartzCore.h>
    
    @interface GraphLayer : CALayer
    
    @property (assign) CGFloat perCent;
    色情報全体でなく、色相hueのみプロパティとする。
    @property (assign) CGFloat hue;
    
    @end
    
[/code]

GraphicLayer.m --------

[code]

    #import "GraphLayer.h"
    
    @implementation GraphLayer {
        CGFloat angle;
        CGFloat radius;
        UIColor *fillColor;
    }
    
    - (id)init {
        self = [super init];
        if (self) {
            // デフォルト値は適当。
            angle = 50.0;
            fillColor = [UIColor blackColor];
            // アニメーション処理に必要らしい。
            self.needsDisplayOnBoundsChange = YES;
            self.contentsScale = [UIScreen mainScreen].scale;
        }
        return self;
    }
    // アニメーション処理に、必要らしい。
    - (id)initWithLayer:(id)layer {
        self = [super initWithLayer: layer];
        if (self) {
            self.needsDisplayOnBoundsChange = YES;
            self.contentsScale = [UIScreen mainScreen].scale;
        }
        return self;
    }
    // CABasicAnimationのkeyPathに対応するキーを指定。
    + (BOOL)needsDisplayForKey: (NSString *)key {
        if ([key isEqualToString: @"perCent"]) {
            return YES;
        } else if ([key isEqualToString: @"hue"]) {
            return YES;
        }
        return [super needsDisplayForKey: key];
    }
    // 描画処理。CGContext〜でなく、CGPathでパスを描いてもいいですよ。
    - (void)drawInContext:(CGContextRef)ctx {
        if (self.frame.size.width >= self.frame.size.height) {
            radius = self.frame.size.height / 2.0;
        } else {
            radius = self.frame.size.width / 2.0;
        }
        CGContextMoveToPoint(ctx, radius, radius);
        CGContextAddArc(ctx, radius, radius, radius, M_PI / -2.0, angle - M_PI / 2.0, 0);
        CGContextClosePath(ctx);
        CGContextSetFillColorWithColor(ctx, fillColor.CGColor);
        CGContextFillPath(ctx);
    }
    
    // Accessor Methods
    // パーセントを角度に変換。
    - (CGFloat)perCent {
        return angle / M_PI * 50.0;
    }
    
    - (void)setPerCent:(CGFloat)perCent {
        angle = M_PI * perCent / 50.0;
    }
    // hueからUIColorを生成。
    - (CGFloat)hue {
        CGFloat theHue;
        [fillColor getHue: &theHue saturation: NULL brightness: NULL alpha: NULL];
        return theHue;
    }
    
    - (void)setHue:(CGFloat)hue {
        fillColor = [[UIColor alloc] initWithHue: hue saturation: 1.0 brightness: 1.0 alpha: 1.0];
    }
    
    @end
    
[/code]

プログラム作成でつまづいたのは、UIColor、CGColorをCABasicAnimationのkeyPathにしたら、アニメーションしてくれないことです。CALayerのプロパティborderColorはCGColorRef型で、アニメーションしくれるので、なにかCGColorRefのままkeyPathにすることができるはずなんですが、興味＜めんどくささになったので、検討中断しました。


CC BY-SA 3.0
2015-03-25T09:52:19.420
8376
2015-03-26T06:49:54.580
2015-03-26T06:49:54.580
7362
7362
8375
answer