正方形とその一辺を半径とする弧を使って、ルート2長方形を作図していくiPhoneアプリを作ってみます。正方形、円弧、ルート2長方形、と描いていき、最後は、ルート2長方形の2等分を繰り返していきます。
動作イメージ
XcodeからiOS6 iPhone Simulatorで動かすとこんな感じになります。
サンプルコード
#import “RalliesViewController.h”
#import <QuartzCore/QuartzCore.h>
@interface RalliesViewController ()
{
int count;
UIView *canvas;
}
@end
@implementation RalliesViewController
– (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [self color:2];
[self createGridSheet];
[self createRegularRect];
[self createButton];
}
– (void)createRegularRect
{
[canvas removeFromSuperview];
canvas = [[UIView alloc] initWithFrame:self.view.bounds];
canvas.backgroundColor = [UIColor clearColor];
[self.view insertSubview:canvas atIndex:0];
UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(50, 150, 150, 150)];
CAShapeLayer *sl = [[CAShapeLayer alloc] init];
sl.fillColor = CGColorCreateCopyWithAlpha([self color:1].CGColor, 0.5);
sl.strokeColor = [self color:0].CGColor;
sl.lineWidth = 2.0;
sl.path = path.CGPath;
[canvas.layer addSublayer:sl];
[self startDraw:sl];
}
– (void)createArcWithSquareRoot
{
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(50, 300)];
[path addLineToPoint:CGPointMake(200, 150)];
[path addArcWithCenter:CGPointMake(50, 300) radius:150.0 * sqrt(2) startAngle:-M_PI/4.0 endAngle:0 clockwise:YES];
[path closePath];
CAShapeLayer *sl = [[CAShapeLayer alloc] init];
sl.fillColor = [UIColor clearColor].CGColor;
sl.strokeColor = [self color:0].CGColor;
sl.lineWidth = 2.0;
sl.path = path.CGPath;
[canvas.layer addSublayer:sl];
[self startDraw:sl];
}
– (void)createSquareRootRectangle
{
float w = 150 * (sqrt(2) – 1.0);
UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(200, 150, w, 150)];
CAShapeLayer *sl = [[CAShapeLayer alloc] init];
sl.fillColor = CGColorCreateCopyWithAlpha([self color:1].CGColor, 0.5);
sl.strokeColor = [self color:0].CGColor;
sl.lineWidth = 2.0;
sl.path = path.CGPath;
[canvas.layer addSublayer:sl];
[self startDraw:sl];
}
– (void)createDivide
{
// init
[canvas removeFromSuperview];
canvas = [[UIView alloc] initWithFrame:self.view.bounds];
canvas.backgroundColor = [UIColor clearColor];
[self.view insertSubview:canvas atIndex:0];
float w = 150 * sqrt(2);
CGRect rects[] = {
CGRectMake(50, 150, w, 150),
CGRectMake(50 + w/2.0, 150, w/2.0, 150),
CGRectMake(50 + w/2.0, 150, w/2.0, 75),
CGRectMake(50 + w/2.0, 150, w/4.0, 75),
CGRectMake(50 + w/2.0, 150 + 75/2.0, w/4.0, 75/2.0),
};
for (int i=0; i<5; i++) {
UIBezierPath *path = [UIBezierPath bezierPathWithRect:rects[i]];
CAShapeLayer *sl = [[CAShapeLayer alloc] init];
sl.fillColor = CGColorCreateCopyWithAlpha([self color:1].CGColor, 0.3);
sl.strokeColor = [self color:0].CGColor;
sl.lineWidth = 2.0;
sl.path = path.CGPath;
sl.strokeEnd = 0.0;
[canvas.layer addSublayer:sl];
[self performSelector:@selector(startDraw:) withObject:sl afterDelay:0.2 * i];
}
}
– (void)createButton
{
UILabel *btn = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
btn.layer.cornerRadius = 50;
btn.center = CGPointMake(160, 420);
btn.text = @”push”;
btn.textAlignment = NSTextAlignmentCenter;
[self.view addSubview:btn];
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(50, 50) radius:60 startAngle:0 endAngle:-M_PI/2.0 clockwise:NO];
[path addLineToPoint:CGPointMake(50, 50)];
[path closePath];
CAShapeLayer *sl = [CAShapeLayer layer];
sl.frame = btn.bounds;
sl.fillColor = CGColorCreateCopyWithAlpha([self color:0].CGColor, 0.5);
sl.path = path.CGPath;
sl.anchorPoint = CGPointMake(0.5, 0.5);
[btn.layer addSublayer:sl];
btn.userInteractionEnabled = YES;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(push:)];
[btn addGestureRecognizer:tap];
}
– (void)push:(UITapGestureRecognizer*)gr
{
count = (count + 1) % 4;
CAShapeLayer *sl = [gr.view.layer.sublayers objectAtIndex:0];
[UIView animateWithDuration:0.3 animations:^{
sl.transform = CATransform3DRotate(sl.transform, M_PI/2.0, 0, 0, 1);
}];
switch (count) {
case 0:
[self createRegularRect];
break;
case 1:
[self createArcWithSquareRoot];
break;
case 2:
[self createSquareRootRectangle];
break;
case 3:
[self createDivide];
break;
default:
break;
}
}
#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.strokeColor = [UIColor whiteColor].CGColor;
sl.lineWidth = 1;
sl.lineDashPattern = @[@8, @2];
sl.path = path.CGPath;
[self.view.layer addSublayer:sl];
}
– (void)startDraw:(CAShapeLayer*)l
{
CABasicAnimation *a = [CABasicAnimation animationWithKeyPath:@”strokeEnd”];
a.duration = 1.0;
a.fromValue = @0;
a.toValue = @1;
[l addAnimation:a forKey:@”strokeEnd”];
if (l.strokeEnd == 0) {
l.strokeEnd = 1.0;
}
}
#define UIColorHex(rgbValue) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 green:((float)((rgbValue & 0xFF00) >> 8))/255.0 blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0]
– (UIColor*)color:(int)i
{
switch (i) {
case 0:
return UIColorHex(0x2C4259);
case 1:
return UIColorHex(0x9ED9D8);
case 2:
return UIColorHex(0xEDE9F0);
case 3:
return UIColorHex(0xFAF5F7);
case 4:
return UIColorHex(0xD4D0D1);
default:
break;
}
return nil;
}
– (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end