今日は三角パズルを作成してみました。
あか、あお、きいろ、みどり、4色のさんかく形を
まわして(タップで回転)、ずらして(ゆびで動かせます)
この二つの操作でさんかくを動かしていくと、
風車とか、船とか、いろいろな形を作ることができます。
プログラムのポイント
「問題」
UIViewに三角を表示しているので、
実際には二枚の四角が重なった状態となります。
ここで下になったViewにtouch eventを渡らない。
「解決法」
タッチしたところの色をCGBitmapContextCreateを使って取得
透明だった場合、上にあるViewのuserInteractionEnabledを一時的にNO
に設定して、下のViewのtouch eventを呼び出す。
詳細はメソッド「touchNotClearColorView」を参照
サンプルコード
#import “ViewController.h”
#import <QuartzCore/QuartzCore.h>
@interface ViewController ()
@end
@implementation ViewController
– (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
[self createPiece];
UISwipeGestureRecognizer *swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(reset)];
[self.view addGestureRecognizer:swipe];
}
– (void)reset
{
for (UIView *v in self.view.subviews) {
[UIView animateWithDuration:2.0 animations:^{
v.transform = CGAffineTransformIdentity;
}];
}
}
– (void) createPiece
{
float w = 80;
NSArray *colors = [NSArray arrayWithObjects:[UIColor redColor], [UIColor blueColor], [UIColor yellowColor], [UIColor greenColor], nil];
for (int i=0; i<8; i++) {
float x = (i % 4) * w;
float y = (i / 4) * w + 280;
// triangle A
UIView *a = [[UIView alloc] initWithFrame:CGRectMake(x, y, w, w)];
a.backgroundColor = [UIColor clearColor];
UIBezierPath *path1 = [[UIBezierPath alloc] init];
[path1 moveToPoint:CGPointMake(0, 0)];
[path1 addLineToPoint:CGPointMake(w, w)];
[path1 addLineToPoint:CGPointMake(w, 0)];
CAShapeLayer *l1 = [[CAShapeLayer alloc] initWithLayer:a.layer];
l1.fillColor = [[colors objectAtIndex:i % 4] CGColor];
l1.path = path1.CGPath;
[a.layer addSublayer:l1];
[self.view addSubview:a];
// triangle B
UIView *b = [[UIView alloc] initWithFrame:CGRectMake(x, y, w, w)];
b.backgroundColor = [UIColor clearColor];
UIBezierPath *path2 = [[UIBezierPath alloc] init];
[path2 moveToPoint:CGPointMake(0, 0)];
[path2 addLineToPoint:CGPointMake(0, w)];
[path2 addLineToPoint:CGPointMake(w, w)];
CAShapeLayer *l2 = [[CAShapeLayer alloc] initWithLayer:b.layer];
l2.fillColor = [[colors objectAtIndex:(i + 1) % 4] CGColor];
l2.path = path2.CGPath;
[b.layer addSublayer:l2];
[self.view addSubview:b];
a.tag = i;
b.tag = i + 100;
}
for (UIView *v in self.view.subviews) {
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap:)];
[v addGestureRecognizer:tap];
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
[v addGestureRecognizer:pan];
}
}
– (void)tap:(UIGestureRecognizer*)gr
{
CGPoint p = [gr locationInView:self.view];
UIView *target = [self touchNotClearColorView:p];
if (target) {
[UIView animateWithDuration:0.5 animations:^{
target.transform = CGAffineTransformRotate(target.transform, M_PI * 0.5);
}];
}
}
– (void)pan:(UIPanGestureRecognizer*)gr
{
static UIView *target;
CGPoint p = [gr locationInView:self.view];
if (gr.state == UIGestureRecognizerStateBegan) {
target = [self touchNotClearColorView:p];
}
else if (gr.state == UIGestureRecognizerStateEnded
|| gr.state == UIGestureRecognizerStateCancelled)
{
target = nil;
}
if (target) {
float currentAngle = [[target.layer valueForKeyPath:@”transform.rotation.z”] floatValue];
target.transform = CGAffineTransformRotate(target.transform, -currentAngle);
float oldx = target.transform.tx + target.center.x;
float oldy = target.transform.ty + target.center.y;
CGPoint t = CGPointMake(p.x – oldx, p.y – oldy);
target.transform = CGAffineTransformTranslate(target.transform, t.x, t.y);
target.transform = CGAffineTransformRotate(target.transform, currentAngle);
}
}
– (UIView*)touchNotClearColorView:(CGPoint)p0
{
UIView *target = nil;
BOOL end = NO;
while (!end) {
target = [self.view hitTest:p0 withEvent:nil];
if (!target || target == self.view) {
target = nil;
end = YES;
}
CGPoint p = [target convertPoint:p0 fromView:target.superview];
if ([self alphaOfPoint:p view:target] == 0) {
target.userInteractionEnabled = NO;
} else {
end = YES;
}
}
for (UIView *v in self.view.subviews) {
v.userInteractionEnabled = YES;
}
return target;
}
– (float)alphaOfPoint:(CGPoint)point view:(UIView*)view
{
unsigned char pixel[4] = {0};
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(pixel, 1, 1, 8, 4, colorSpace, kCGImageAlphaPremultipliedLast);
CGContextTranslateCTM(context, -point.x, -point.y);
[view.layer renderInContext:context];
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
float alpha = pixel[3]/255.0;
return alpha;
}
– (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end