iPhone Piチャート3D

3Dの円グラフを表示するiPhoneアプリのサンプルコードを描いてみます。

#import “ViewController.h”

@import SceneKit;

@interface ViewController ()

@property (nonatomic, weak) SCNView *sceneView;

@property (nonatomic, strong) NSMutableArray *sliders;

@end

@implementation ViewController

– (void)viewDidLoad {

    [super viewDidLoad];

    [self setupScene];

    

    [self createSlider];

    [self createPiChart];

    [self createCamera];

}

– (void)setupScene {

    SCNView *sv = [[SCNView alloc] initWithFrame:self.view.bounds];

    sv.scene = [SCNScene scene];

    sv.autoenablesDefaultLighting = YES;

    sv.backgroundColor = [self color:0];

    [self.view addSubview:sv];

    self.sceneView = sv;

}

– (void)createPiChart {

    

    for (int i=0; i<3; i++) {

        UIBezierPath *path = [UIBezierPath bezierPath];

        SCNShape *arc = [SCNShape shapeWithPath:path extrusionDepth:4.0];

        arc.firstMaterial.diffuse.contents = [self color:i+1];

        SCNNode *node = [SCNNode nodeWithGeometry:arc];

        node.name = @[@”chartA”, @”chartB”, @”chartC”][i];

        [self.sceneView.scene.rootNode addChildNode:node];

    }

    

    [self updatePiChart];

}

– (void)updatePiChart {

    

    float startAngle = 0;

    float endAngle = 0;

    for (int i=0; i<3; i++) {

        NSString *name = @[@”chartA”, @”chartB”, @”chartC”][i];

        endAngle += ((UISlider *)self.sliders[i]).value;

        

        SCNNode *node = [self.sceneView.scene.rootNode childNodeWithName:name recursively:NO];

        UIBezierPath *path = [UIBezierPath bezierPath];

        [path moveToPoint:CGPointZero];

        

        float r = 20;

        float dAngle = 2.0 * M_PI / (((UISlider *)self.sliders[0]).value

                                     + ((UISlider *)self.sliders[1]).value

                                     + ((UISlider *)self.sliders[2]).value);

        for (float i=startAngle; i<endAngle; i+=0.1) {

            [path addLineToPoint:CGPointMake(r * cos(dAngle * i), r * sin(dAngle * i))];

        }

        [path addLineToPoint:CGPointMake(r * cos(dAngle * endAngle), r * sin(dAngle * endAngle))];

        [path closePath];

        ((SCNShape *)node.geometry).path = path;

        

        startAngle = endAngle;

    }

}

– (void)createSlider {

    

    self.sliders = [NSMutableArray array];

    

    for (int i=0; i<3; i++) {

        UISlider *slider = [[UISlider alloc] init];

        slider.center = CGPointMake(CGRectGetMidX(self.view.bounds), CGRectGetMaxY(self.view.bounds) – 200 + 50 * i);

        slider.minimumValue = 1.0;

        slider.maximumValue = 100.0;

        slider.value = 100.0/3.0;

        [self.view addSubview:slider];

        

        [slider addTarget:self action:@selector(slide:) forControlEvents:UIControlEventValueChanged];

        [self.sliders addObject:slider];

    }

}

– (void)slide:(UISlider *)sender {

    [self updatePiChart];

}

– (void)createCamera {

    SCNNode *camera = [SCNNode node];

    camera.camera = [SCNCamera camera];

    camera.position = SCNVector3Make(0, –50, 50);

    camera.rotation = SCNVector4Make(1, 0, 0, 0.6);

    [self.sceneView.scene.rootNode addChildNode:camera];

}

#define ColorHex(rgb) [UIColor colorWithRed:((rgb & 0xFF0000) >> 16)/255.0 green:((rgb & 0xFF00) >> 8)/255.0 blue:(rgb &0xFF)/255.0 alpha:1.0]

– (UIColor *)color:(int)i {

    switch (i) {

        case 0: return ColorHex(0xE9F1DF);

        case 1: return ColorHex(0xF2385A);

        case 2: return ColorHex(0xF5A503);

        case 3: return ColorHex(0x4AD9D9);

    }

    return nil;

}

@end