トリックアート
市松模様が動いているように見える図形を書いてみる。
横長の長方形をタイル上に並べて、
その真ん中に縦長の長方形でできた円を配置する。

補足
自分で試したところ、何となく動いている気もする。
模様を目から近づけたり遠ざけたりすると、外の長方形が伸縮して見えた。
なにか、根本的なところが足りないのかも?

プログラム上のポイント

回転するイチマツ円の作り方:
長方形を配置したUIViewからUIImageを取得して、
コレを新しいUIImageViewに円上に書き込んでくるっとまわせば完成。
UIGraphicsBeginImageContextを使って実現です。

円の回転:
PanGestureRecognizerで円の中心点P0とタッチしているポイントP1を
convertPointを使って円の座標で取得 (P0はconvertPointで、P1は
locationInViewで円のUIViewを指定した)。この2点からatanで角度を計算
これを、CGAffineTransformMakeRotationに使ってクルクルする。


サンプルコード

#import “ViewController.h”

#import <QuartzCore/QuartzCore.h>

@interface ViewController () {

    float dw;

    float dh;

}

@end

@implementation ViewController

– (void)viewDidLoad

{

    [super viewDidLoad];

    

    // initial size

    dw = 80.0;

    dh = 10.0;

    

    UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinch:)];

    [self.view addGestureRecognizer:pinch];    

    

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

    [self.view addGestureRecognizer:tap];

    

    [self createRectBlackWhite];

}

– (void)pinch:(UIPinchGestureRecognizer*)gr

{

    static float begin;

    if (gr.state == UIGestureRecognizerStateBegan) {

        begin = gr.scale;

    }

    

    float dif = (gr.scale – begin) / 10.0;

    dw = MIN(40 * 8, MAX(dw + dif * 8, 5 * 8));

    dh = MIN(40, MAX(dh + dif, 5));

    

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

        [v removeFromSuperview];

    }

    [self createRectBlackWhite];

}

– (void)tap:(UITapGestureRecognizer*)gr

{

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

    if (gr.state == UIGestureRecognizerStateEnded) {

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

        v.backgroundColor = [UIColor clearColor];

        

        UIGraphicsBeginImageContext([v.layer frame].size);

        CGContextRef ctx = UIGraphicsGetCurrentContext();

        CGContextTranslateCTM(ctx, 100-p.x, 100-p.y);

        [self.view.layer renderInContext:UIGraphicsGetCurrentContext()];

        UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();

        

        UIGraphicsEndImageContext();

                

        v.image = outputImage;

        v.contentMode = UIViewContentModeScaleAspectFit;

        v.layer.masksToBounds = YES;

        v.layer.cornerRadius = 100.0;

        v.backgroundColor = [UIColor blackColor];

        v.center = p;

        v.userInteractionEnabled = YES;

        [self.view addSubview:v];

        

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

        [v addGestureRecognizer:pan];

    }

}

– (void)turn:(UIPanGestureRecognizer*)gr

{

    gr.view.transform = CGAffineTransformIdentity;

    CGPoint p1 = [gr locationInView:gr.view];

    CGPoint p0 = [self.view convertPoint:gr.view.center toView:gr.view];

    

    float angle = atan2f(p1.y – p0.y, p1.x – p0.x);

    gr.view.transform = CGAffineTransformMakeRotation(angle);

}

– (void)createRectBlackWhite

{

    float wMax = self.view.bounds.size.width;

    float hMax = self.view.bounds.size.height;

    for (int w=0; w<wMax/dw; w++) {

        for (int h=0; h<hMax/dh; h++) {

            CGRect rect = CGRectMake(w * dw, h * dh, dw, dh);

            UIView *v = [[UIView alloc] initWithFrame:rect];

            if ((h+w) % 2 == 1) {

                v.backgroundColor = [UIColor blackColor];

            } else {

                v.backgroundColor = [UIColor whiteColor];

            }

            [self.view addSubview:v];

        }

    }

}

– (void)didReceiveMemoryWarning

{

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}

@end