線の長さが同じに見えなくなる視覚トリックを自分で作って試してみる。

(XcodeのiOS6 iPhone Simulatorで試しています。)

ポイント

・CAShapeLayerとUIBezierPathを使って矢印ボタンを作る

・矢印の種類を選択するコンソールを用意

・線をタップすると選択している矢印に変わるようにする

サンプルコード

#import “ViewController.h”

#import <QuartzCore/QuartzCore.h>

typedef enum {

    ArrowType0,

    ArrowType1,

    ArrowType2,

} ArrowType;

@interface ViewController () {

    UIView *console;

    UIView *mark;

    ArrowType type;

}

@end

@implementation ViewController

– (void)viewDidLoad

{

    [super viewDidLoad];

    

    [self createBackGround];

    

    [self createLines];

    

    [self createConsole];

    

    // title

    UILabel *title = [[UILabel alloc] init];

    title.text = @”optical illusion 1″;

    [title sizeToFit];

    title.center = CGPointMake(80, 20);

    title.backgroundColor = [UIColor clearColor];

    [self.view addSubview:title];

}

– (void)createBackGround

{

    self.view.backgroundColor = [UIColor yellowColor];

    float hue, saturation, brightness, alpha;

    [[UIColor yellowColor] getHue:&hue saturation:&saturation brightness:&brightness alpha:&alpha];

    

    UIColor *innerColor = [UIColor colorWithHue:hue saturation:saturation brightness:brightness – 0.2 alpha:alpha];

    UIView *innerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 420)];

    innerView.backgroundColor = innerColor;

    innerView.center = CGPointMake(self.view.bounds.size.width/2.0, self.view.bounds.size.height/2.0);

    

    [self.view addSubview:innerView];

}

– (void)createLines

{

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

        UIView *v = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 20)];

        v.center = CGPointMake(160, (i) * 40 + 80);

        v.backgroundColor = [UIColor clearColor];

        UIView *line = [[UIView alloc] initWithFrame:CGRectMake(0,8,200,4)];

        line.backgroundColor = [UIColor blackColor];

        [v addSubview:line];

        

        [self.view addSubview:v];

        

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

        [v addGestureRecognizer:tap];

    }

}

– (void)createConsole

{

    console = [[UIView alloc] initWithFrame:CGRectMake(0,0,240,60)];

    console.backgroundColor = [UIColor blackColor];

    console.center = CGPointMake(160, 370);

    [self.view addSubview:console];

    

    // 矢印 <—>

    UIView *one = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];

    one.layer.cornerRadius = 5.0;

    one.layer.borderWidth = 2.0;

    one.layer.borderColor = [UIColor whiteColor].CGColor;

    one.center = CGPointMake(40, 30);

    [console addSubview:one];

    CAShapeLayer * shapeLayer = [CAShapeLayer layer];

    shapeLayer.frame = CGRectMake(0,0,40,40);

    shapeLayer.backgroundColor = [UIColor clearColor].CGColor;

    shapeLayer.strokeColor = [UIColor whiteColor].CGColor;

    shapeLayer.lineWidth = 4.0;

    UIBezierPath* aPath = [UIBezierPath bezierPath];

[aPath moveToPoint:CGPointMake(35, 10)];

[aPath addLineToPoint:CGPointMake(25, 20)];

[aPath addLineToPoint:CGPointMake(35, 30)];

[aPath moveToPoint:CGPointMake(5, 10)];

[aPath addLineToPoint:CGPointMake(15, 20)];

[aPath addLineToPoint:CGPointMake(5, 30)];

    shapeLayer.path = aPath.CGPath;

    

    [one.layer addSublayer:shapeLayer];

    

    // 矢印 >—<

    UIView *two = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];

    two.layer.cornerRadius = 5.0;

    two.layer.borderWidth = 2.0;

    two.layer.borderColor = [UIColor whiteColor].CGColor;

    two.center = CGPointMake(120, 30);

    [console addSubview:two];

    shapeLayer = [CAShapeLayer layer];

    shapeLayer.frame = CGRectMake(0,0,40,40);

    shapeLayer.backgroundColor = [UIColor clearColor].CGColor;

    shapeLayer.strokeColor = [UIColor whiteColor].CGColor;

    shapeLayer.lineWidth = 4.0;

    aPath = [UIBezierPath bezierPath];

[aPath moveToPoint:CGPointMake(25, 10)];

[aPath addLineToPoint:CGPointMake(35, 20)];

[aPath addLineToPoint:CGPointMake(25, 30)];

[aPath moveToPoint:CGPointMake(15, 10)];

[aPath addLineToPoint:CGPointMake(5, 20)];

[aPath addLineToPoint:CGPointMake(15, 30)];

    shapeLayer.path = aPath.CGPath;

    

    [two.layer addSublayer:shapeLayer];

    

    // 線のみ

    UIView *thr = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];

    thr.layer.cornerRadius = 5.0;

    thr.layer.borderWidth = 2.0;

    thr.layer.borderColor = [UIColor whiteColor].CGColor;

    thr.center = CGPointMake(200, 30);

    [console addSubview:thr];

    shapeLayer = [CAShapeLayer layer];

    shapeLayer.frame = CGRectMake(0,0,40,40);

    shapeLayer.backgroundColor = [UIColor clearColor].CGColor;

    shapeLayer.strokeColor = [UIColor whiteColor].CGColor;

    shapeLayer.lineWidth = 4.0;

    aPath = [UIBezierPath bezierPath];

[aPath moveToPoint:CGPointMake(5, 20)];

[aPath addLineToPoint:CGPointMake(35, 20)];

    shapeLayer.path = aPath.CGPath;

    

    [thr.layer addSublayer:shapeLayer];

    

    // Gesture

    one.tag = ArrowType1;

    two.tag = ArrowType2;

    thr.tag = ArrowType0;

    NSArray *arr = [NSArray arrayWithObjects:one, two, thr, nil];

    for (UIView *v in arr) {

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

        [v addGestureRecognizer:tap];

    }

    

    // 選択マーク

    mark = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 60, 60)];

    mark.backgroundColor = [UIColor greenColor];

    mark.alpha = 0.5;

    mark.layer.cornerRadius = 25.0;

    mark.center = thr.center;

    [console addSubview:mark];

}

– (void)tapLine:(UIGestureRecognizer*)gr

{

    [self changeView:gr.view];

}

– (void)tapArrow:(UIGestureRecognizer*)gr

{

    type = gr.view.tag;

    [UIView animateWithDuration:0.2 animations:^{

        mark.center = gr.view.center;

    }];

}

– (void)changeView:(UIView*)v

{

    for (CALayer *l in v.layer.sublayers) {

        if ([l isKindOfClass:[CAShapeLayer class]]) {

            [l removeFromSuperlayer];

        }

    }

    

    float x = v.bounds.size.width;

    float y = v.bounds.size.height * 0.5;

    

    if (type == ArrowType1) {

        

        CAShapeLayer *shapeLayer = [CAShapeLayer layer];

        shapeLayer.frame = CGRectMake(0,0,40,40);

        shapeLayer.strokeColor = [UIColor blackColor].CGColor;

        shapeLayer.fillColor = [UIColor clearColor].CGColor;

        shapeLayer.lineWidth = 4.0;

        UIBezierPath *aPath = [UIBezierPath bezierPath];

        [aPath moveToPoint:CGPointMake(-20, y-10)];

        [aPath addLineToPoint:CGPointMake(0, y)];

        [aPath addLineToPoint:CGPointMake(-20, y+10)];

        [aPath moveToPoint:CGPointMake(x+20, y-10)];

        [aPath addLineToPoint:CGPointMake(x, y)];

        [aPath addLineToPoint:CGPointMake(x+20, y+10)];

        shapeLayer.path = aPath.CGPath;

        [v.layer addSublayer:shapeLayer];

    } else if (type == ArrowType2) {

        

        CAShapeLayer *shapeLayer = [CAShapeLayer layer];

        shapeLayer.frame = CGRectMake(0,0,40,40);

        shapeLayer.strokeColor = [UIColor blackColor].CGColor;

        shapeLayer.fillColor = [UIColor clearColor].CGColor;

        shapeLayer.lineWidth = 4.0;

        UIBezierPath *aPath = [UIBezierPath bezierPath];

        [aPath moveToPoint:CGPointMake(20, y-10)];

        [aPath addLineToPoint:CGPointMake(0, y)];

        [aPath addLineToPoint:CGPointMake(20, y+10)];

        [aPath moveToPoint:CGPointMake(x-20, y-10)];

        [aPath addLineToPoint:CGPointMake(x, y)];

        [aPath addLineToPoint:CGPointMake(x-20, y+10)];

        shapeLayer.path = aPath.CGPath;

        [v.layer addSublayer:shapeLayer];

    }

}

– (void)didReceiveMemoryWarning

{

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}

@end