五角形から黄金三角形(頂角:32°、底角72°の二等辺三角形)の作図過程をアニメーションで表示するiPhoneアプリを書いていきます。
動作イメージ
XcodeからiOS6 iPhone Simulatorで動かすとこんな感じになります。
ポイント
五角形を書いて、その底角と頂角を線で結ぶと黄金三角形の出来上がりです。説明文を表示するコンソールにボタン1とボタン2を配置して押された番号に合わせて、1なら黄金三角形を一つ、2なら黄金三角形を二つ表示するようにしました。
サンプルコード
#import “ViewController.h”
#import <QuartzCore/QuartzCore.h>
@interface ViewController () {
UILabel *console;
CAShapeLayer *pentagon;
CAShapeLayer *lineLayer;
CGPoint vertex[5];
NSMutableArray *angleLabels;
}
@end
@implementation ViewController
– (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
[self createGridSheet];
[self createConsole];
[self createPentagon];
}
– (void)createPentagon
{
float r = 140;
float dAngle = 2 * M_PI / 5.0;
CGPoint o = CGPointMake(160, 380);
for (int i=0; i<5; i++) {
float angle = dAngle * i – M_PI/2.0;
float x = r * cos(angle) + o.x;
float y = r * sin(angle) + o.y;
vertex[i] = CGPointMake(x, y);
}
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:vertex[0]];
for (int i=1; i<5; i++) {
[path addLineToPoint:vertex[i]];
}
[path closePath];
pentagon = [[CAShapeLayer alloc] init];
pentagon.fillColor = [UIColor clearColor].CGColor;
pentagon.strokeColor = [UIColor blackColor].CGColor;
pentagon.lineWidth = 1;
pentagon.path = path.CGPath;
[self.view.layer addSublayer:pentagon];
}
– (void)createConsole
{
console = [[UILabel alloc] initWithFrame:CGRectMake(20, 20, 280, 280/1.618)];
console.backgroundColor = [UIColor colorWithWhite:0 alpha:0.5];
console.text = @”黄金三角形の書き方“;
console.textAlignment = NSTextAlignmentCenter;
console.textColor = [UIColor whiteColor];
[self.view addSubview:console];
for (int i=0; i<2; i++) {
float x = console.bounds.size.width – 45 * (2-i);
float y = console.bounds.size.height – 45;
UILabel *btn = [[UILabel alloc] initWithFrame:CGRectMake(x, y, 40, 40)];
btn.layer.cornerRadius = 20;
btn.text = [NSString stringWithFormat:@”%d”, i + 1];
btn.textAlignment = NSTextAlignmentCenter;
btn.font = [UIFont boldSystemFontOfSize:20];
btn.textColor = [UIColor lightGrayColor];
btn.backgroundColor = [UIColor clearColor];
btn.layer.borderColor = [UIColor lightGrayColor].CGColor;
btn.layer.borderWidth = 4.0;
[console addSubview:btn];
console.userInteractionEnabled = YES;
btn.userInteractionEnabled = YES;
btn.tag = i + 1;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapButton:)];
[btn addGestureRecognizer:tap];
}
}
– (void)tapButton:(UITapGestureRecognizer*)gr
{
switch (gr.view.tag) {
case 1:
[self showGoldenTriangleFromPentagon];
break;
case 2:
[self showSecondaryGoldenTriangleFromPentagon];
break;
default:
break;
}
}
– (void)showGoldenTriangleFromPentagon
{
[self clearCanvas];
[self createPentagon];
console.text = @”五角形の底角と頂点を結ぶ“;
lineLayer = [[CAShapeLayer alloc] init];
lineLayer.strokeColor = [UIColor redColor].CGColor;
lineLayer.fillColor = [UIColor colorWithRed:1 green:0 blue:0 alpha:0.3].CGColor;
lineLayer.lineWidth = 2.0;
[self.view.layer addSublayer:lineLayer];
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:vertex[0]];
[path addLineToPoint:vertex[2]];
[path addLineToPoint:vertex[3]];
[path closePath];
lineLayer.path = path.CGPath;
[self startDraw:lineLayer duration:1.5];
// 角度を表示
CGPoint p[] = {
CGPointMake(vertex[0].x, vertex[0].y + 40),
CGPointMake(vertex[2].x – 20, vertex[2].y – 20),
CGPointMake(vertex[3].x + 20, vertex[3].y – 20),
};
NSArray *angles = @[@”36°”, @”72°”, @”72°”];
for (int i=0; i<3; i++) {
UILabel *angleLabel = [[UILabel alloc] init];
angleLabel.text = [angles objectAtIndex:i];
angleLabel.backgroundColor = [UIColor clearColor];
[angleLabel sizeToFit];
angleLabel.center = p[i];
angleLabel.alpha = 0;
[self.view addSubview:angleLabel];
if (!angleLabels) {
angleLabels = [[NSMutableArray alloc] init];
}
[angleLabels addObject:angleLabel];
[UIView animateWithDuration:1.0 animations:^{
angleLabel.alpha = 1.0;
}];
}
}
– (void)showSecondaryGoldenTriangleFromPentagon
{
[self clearCanvas];
[self createPentagon];
console.text = @”二次的な黄金三角形“;
lineLayer = [[CAShapeLayer alloc] init];
lineLayer.strokeColor = [UIColor redColor].CGColor;
lineLayer.fillColor = [UIColor colorWithRed:1 green:0 blue:0 alpha:0.3].CGColor;
lineLayer.lineWidth = 2.0;
[self.view.layer addSublayer:lineLayer];
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:vertex[0]];
[path addLineToPoint:vertex[2]];
[path addLineToPoint:vertex[3]];
[path closePath];
[path moveToPoint:vertex[1]];
[path addLineToPoint:vertex[3]];
[path addLineToPoint:vertex[4]];
[path closePath];
lineLayer.path = path.CGPath;
[self startDraw:lineLayer duration:1.5];
// 角度を表示
CGPoint p[] = {
CGPointMake(vertex[0].x + 5, vertex[0].y + 30),
CGPointMake(vertex[2].x – 60, vertex[1].y – 10),
CGPointMake(vertex[3].x + 70, vertex[1].y – 10),
CGPointMake(vertex[1].x – 25, vertex[1].y + 10),
CGPointMake(vertex[1].x – 80, vertex[1].y + 10),
CGPointMake(vertex[1].x – 70, vertex[1].y + 40),
CGPointMake(vertex[3].x + 40, vertex[3].y – 10),
CGPointMake(vertex[2].x – 20, vertex[2].y – 10),
CGPointMake(vertex[2].x – 40, vertex[2].y – 70),
};
NSArray *angles = @[@”36°”, @”72°”, @”72°”];
for (int i=0; i<9; i++) {
UILabel *angleLabel = [[UILabel alloc] init];
angleLabel.text = [angles objectAtIndex:i%3];
angleLabel.backgroundColor = [UIColor clearColor];
[angleLabel sizeToFit];
angleLabel.center = p[i];
angleLabel.alpha = 0;
[self.view addSubview:angleLabel];
if (!angleLabels) {
angleLabels = [[NSMutableArray alloc] init];
}
[angleLabels addObject:angleLabel];
[UIView animateWithDuration:1.0 animations:^{
angleLabel.alpha = 1.0;
}];
}
}
– (void)clearCanvas
{
[pentagon removeFromSuperlayer];
[lineLayer removeFromSuperlayer];
for (UIView *v in angleLabels) {
[v removeFromSuperview];
}
[angleLabels removeAllObjects];
}
#pragma mark – utility methods
– (void)createGridSheet
{
UIBezierPath *path = [UIBezierPath bezierPath];
float size = 32;
for (int i=0; i<320/size; i++) {
[path moveToPoint:CGPointMake(i * size, 0)];
[path addLineToPoint:CGPointMake(i * size, 568)];
}
for (int i=0; i<568/size; i++) {
[path moveToPoint:CGPointMake(0, i*size)];
[path addLineToPoint:CGPointMake(320, i*size)];
}
CAShapeLayer *sl = [[CAShapeLayer alloc] init];
sl.fillColor = [UIColor clearColor].CGColor;
sl.strokeColor = [UIColor greenColor].CGColor;
sl.lineWidth = 2;
sl.lineDashPattern = @[@8, @2];
sl.path = path.CGPath;
[self.view.layer addSublayer:sl];
}
– (void)startDraw:(CALayer*)l duration:(float)duration
{
CABasicAnimation *a = [CABasicAnimation animationWithKeyPath:@”strokeEnd”];
a.duration = duration;
a.fromValue = @0;
a.toValue = @1;
[l addAnimation:a forKey:@”strokeEnd”];
}
– (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end