ハーマングリッド (Hermann Grid) 視覚トリックを作ってみる。
(XcodeのiOS6 iPhone Simulatorで動かしています。)

概要

黒の上に、格子状に道を通していくと、
交差点に、無いはずの黒っぽい物がちらちらする
という視覚トリックを作ってみます。
交差点を丸くすると、顕著にチラチラがでてくるので、
ボタンで交差点を丸くできるようにしてみます。

ポイント

画面の下の方に、コントロール用のボタンを2つ用意
左のボタン:左右になぞると格子の大きさを変更
右のボタン:交差点を丸い形にする
黒のUIViewを灰色の背景の上に配置することで、
格子を表示する。



サンプルコード

#import “ViewController.h”

#import <QuartzCore/QuartzCore.h>

@interface ViewController () {

    float edge;

    float border;

    BOOL roundCorner;

}

@end

@implementation ViewController

– (void)viewDidLoad

{

    [super viewDidLoad];

[self createGrid];

    [self createUI];

}

– (void)createGrid

{

    edge = 20;

    border = 5;

    [self updateGrid];

}

– (void)createUI

{

    // grid size changer

    UIView *panel = [[UIView alloc] initWithFrame:CGRectMake(20, 380, 200, 60)];

    panel.backgroundColor = [UIColor whiteColor];

    [self.view addSubview:panel];

    

    UIBezierPath *path = [[UIBezierPath alloc] init];

    [path moveToPoint:CGPointMake(0, 60)];

    [path addLineToPoint:CGPointMake(200, 60)];

    [path addLineToPoint:CGPointMake(200, 0)];

    CAShapeLayer *s = [[CAShapeLayer alloc] initWithLayer:panel];

    s.fillColor = [UIColor blackColor].CGColor;

    s.path = path.CGPath;

    [panel.layer addSublayer:s];

    

    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];

    [panel addGestureRecognizer:pan];

    

    

    // connector shape

    UIView *btn = [[UIView alloc] initWithFrame:CGRectMake(240, 380, 60, 60)];

    btn.backgroundColor = [UIColor whiteColor];

    [self.view addSubview:btn];

    

    UIBezierPath *path2 = [[UIBezierPath alloc] init];

    [path2 moveToPoint:CGPointMake(0, 30)];

    [path2 addLineToPoint:CGPointMake(60, 30)];

    [path2 moveToPoint:CGPointMake(30, 0)];

    [path2 addLineToPoint:CGPointMake(30, 60)];

    [path2 moveToPoint:CGPointMake(30, 30)];

    [path2 addArcWithCenter:CGPointMake(30, 30) radius:5 startAngle:0 endAngle:M_PI*2 clockwise:NO];

    CAShapeLayer *s2 = [[CAShapeLayer alloc] initWithLayer:btn];

    s2.fillColor = [UIColor clearColor].CGColor;

    s2.strokeColor = [UIColor blackColor].CGColor;

    s2.lineWidth = 5.0;

    s2.path = path2.CGPath;

    [btn.layer addSublayer:s2];

    

    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap:)];

    [btn addGestureRecognizer:tap];

}

– (void)pan:(UIGestureRecognizer*)gr

{

    CGPoint p = [gr locationInView:self.view];

    

    if (p.x < 20) {

        p.x = 20;

    }

    

    if (p.x > 220) {

        p.x = 220;

    }

    

    edge = p.x / 4.0;

    border = edge / 4.0;

    

    [self updateGrid];

}

– (void)updateGrid

{

    for (UIView *v in self.view.subviews) {

        if (v.tag == 1) {

            [v removeFromSuperview];

        }

    }

    

    CGSize size = self.view.bounds.size;

    

    for (int i=0; i<size.width/(edge+border); i++) {

        for (int j=0; j<(size.height)/(edge+border); j++) {

            float x = i * (edge + border);

            float y = 300 – j * (edge + border);

            

            UIView *v = [[UIView alloc] initWithFrame:CGRectMake(x, y, edge, edge)];

            v.backgroundColor = [UIColor blackColor];

            v.tag = 1;

            [self.view insertSubview:v atIndex:0];

            

            if (roundCorner) {

                UIView *round = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 2*border, 2*border)];

                round.center = CGPointMake(x – border*0.5, y-border*0.5);

                round.layer.cornerRadius = border;

                round.backgroundColor = [UIColor whiteColor];

                round.tag = 1;

                [self.view addSubview:round];

            }

        }

    }

}

– (void)tap:(UIGestureRecognizer*)gr

{

    roundCorner = !roundCorner;

    [self updateGrid];

}

– (void)didReceiveMemoryWarning

{

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}

@end