【iOS】【Objective-C】アニメーション付き円グラフ

円グラフをアニメーション付きに。下のような感じで。

<img src="https://oneworld2.sakura.ne.jp/blog/graph1.gif" width=100>
<img src="https://oneworld2.sakura.ne.jp/blog/graph2.gif" width=100>
gifちらつきますが..


真ん中くりぬきと、そうじゃないバージョンで。

まずはObjective-C版を。
valueとcolorを渡すイメージで実装。

```objc:PieGraphView.m

#import "PieGraphView.h"

@implementation PieGraphView
{
    NSArray *_params;
    float _end_angle;
}

-(PieGraphView*)initWithFrame:(CGRect)frame params:(NSArray*)params
{
    self = [super initWithFrame:frame];
    if (self) {
        _params = params;
        self.backgroundColor = [UIColor clearColor];
        _end_angle = -M_PI / 2;
    }
    return self;
}


-(void)update:(id)link{
    _end_angle +=  (M_PI*2 )/ 100;
    if(_end_angle > M_PI*2) {
        //終了
        [link invalidate];
    } else {
        [self setNeedsDisplay];
    }
}

//開始メソッド
-(void)startAnimating
{
    CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(update:)];
    [link addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
}


// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    // Drawing code
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGFloat x = rect.origin.x;
    x += rect.size.width/2;
    CGFloat y = rect.origin.y;
    y += rect.size.height/2;
    float max = 0;
    for(NSDictionary *dic in _params){
        float value = [dic[@"value"] floatValue];
        max += value;
    }

    
    float start_angle = -M_PI / 2;
    float end_angle   = 0;
    float radius = x-10;
    for(NSDictionary *dic in _params){
        float   value = [dic[@"value"] floatValue];
        end_angle = start_angle + M_PI*2 * (value/max);
        if(end_angle > _end_angle) {
            end_angle = _end_angle;
        }
        UIColor *color = dic[@"color"];
        CGContextMoveToPoint(context, x, y);
        CGContextAddArc(context, x, y, radius,  start_angle, end_angle, 0);
//これを有効にすると、中をくりぬき
//        CGContextAddArc(context, x, y, radius/2,  end_angle, start_angle, true);
        CGContextSetFillColor(context, CGColorGetComponents([color CGColor]));
        CGContextClosePath(context);
        CGContextFillPath(context);
        start_angle = end_angle;
    }

}

@end

```

```objc:PieGraphView.h

#import <UIKit/UIKit.h>

@interface PieGraphView : UIView
-(PieGraphView*)initWithFrame:(CGRect)frame params:(NSArray*)params;
-(void)startAnimating;
@end

```


利用イメージは以下のようなものを検討しています。

```objc:ViewController.m


- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    NSMutableArray *params = [[NSMutableArray alloc] init];
    [params addObject:@{@"value":@7,@"color":[UIColor redColor]}];
    [params addObject:@{@"value":@5,@"color":[UIColor blueColor]}];
    [params addObject:@{@"value":@8,@"color":[UIColor greenColor]}];
    [params addObject:@{@"value":@10,@"color":[UIColor yellowColor]}];
    graphView = [[PieGraphView alloc] initWithFrame:CGRectMake(0, 30, 320, 320) params:params];
    [self.view addSubview:graphView];
}

- (IBAction)start:(id)sender {
    [graphView startAnimating];
}


```