iOS 利用CATransform3D制作立方体
1 #import <UIKit/UIKit.h>
2 #import <QuartzCore/QuartzCore.h>
3
4 @interface BoxViewController : UIViewController
5 @property (nonatomic, readwrite, strong) CALayer *topLayer;
6 @property (nonatomic, readwrite, strong) CALayer *bottomLayer;
7 @property (nonatomic, readwrite, strong) CALayer *leftLayer;
8 @property (nonatomic, readwrite, strong) CALayer *rightLayer;
9 @property (nonatomic, readwrite, strong) CALayer *frontLayer;
10 @property (nonatomic, readwrite, strong) CALayer *backLayer;
11 @end
1 #import "BoxViewController.h"
2
3 @implementation BoxViewController
4
5 const CGFloat kSize = 100.;
6 const CGFloat kPanScale = 1./100.;
7
8 - (CALayer *)layerWithColor:(UIColor *)color
9 transform:(CATransform3D)transform {
10 CALayer *layer = [CALayer layer];
11 layer.backgroundColor = [color CGColor];
12 layer.bounds = CGRectMake(0, 0, kSize, kSize);
13 layer.position = self.view.center;
14 layer.transform = transform;
15 [self.view.layer addSublayer:layer];
16 return layer;
17 }
18
19 static CATransform3D MakePerspetiveTransform() {
20 CATransform3D perspective = CATransform3DIdentity;
21 perspective.m34 = -1./2000.;
22 return perspective;
23 }
24
25 - (void)viewDidLoad {
26 [super viewDidLoad];
27
28 CATransform3D transform;
29 transform = CATransform3DMakeTranslation(0, -kSize/2, 0);
30 transform = CATransform3DRotate(transform, M_PI_2, 1.0, 0, 0);
31 self.topLayer = [self layerWithColor:[UIColor redColor]
32 transform:transform];
33
34 transform = CATransform3DMakeTranslation(0, kSize/2, 0);
35 transform = CATransform3DRotate(transform, M_PI_2, 1.0, 0, 0);
36 self.bottomLayer = [self layerWithColor:[UIColor greenColor]
37 transform:transform];
38
39 transform = CATransform3DMakeTranslation(kSize/2, 0, 0);
40 transform = CATransform3DRotate(transform, M_PI_2, 0, 1, 0);
41 self.rightLayer = [self layerWithColor:[UIColor blueColor]
42 transform:transform];
43
44 transform = CATransform3DMakeTranslation(-kSize/2, 0, 0);
45 transform = CATransform3DRotate(transform, M_PI_2, 0, 1, 0);
46 self.leftLayer = [self layerWithColor:[UIColor cyanColor]
47 transform:transform];
48
49 transform = CATransform3DMakeTranslation(0, 0, -kSize/2);
50 transform = CATransform3DRotate(transform, M_PI_2, 0, 0, 0);
51 self.backLayer = [self layerWithColor:[UIColor yellowColor]
52 transform:transform];
53
54 transform = CATransform3DMakeTranslation(0, 0, kSize/2);
55 transform = CATransform3DRotate(transform, M_PI_2, 0, 0, 0);
56 self.frontLayer = [self layerWithColor:[UIColor magentaColor]
57 transform:transform];
58
59 self.view.layer.sublayerTransform = MakePerspetiveTransform();
60
61 UIGestureRecognizer *g = [[UIPanGestureRecognizer alloc]
62 initWithTarget:self
63 action:@selector(pan:)];
64 [self.view addGestureRecognizer:g];
65 }
66
67 - (void)pan:(UIPanGestureRecognizer *)recognizer {
68 CGPoint translation = [recognizer translationInView:self.view];
69 CATransform3D transform = MakePerspetiveTransform();
70 transform = CATransform3DRotate(transform,
71 kPanScale * translation.x,
72 0, 1, 0);
73 transform = CATransform3DRotate(transform,
74 -kPanScale * translation.y,
75 1, 0, 0);
76 self.view.layer.sublayerTransform = transform;
77 }
78
79 @end
第59行的 self.view.layer.sublayerTransform = MakePerspetiveTransform(); 是给self.view.layer的子图层添加 景深效果,之所以有景深效果,是因为perspective.m34 = -1./2000.
m34的值越接近0,则景深效果越明显。
上面这种方法称之为透视变形。
还有一种方法:利用CATransformLayer制作立方体
1 #import <UIKit/UIKit.h>
2 #import <QuartzCore/QuartzCore.h>
3
4 @interface BoxTransformViewController : UIViewController
5 @property (nonatomic, readwrite, strong) CALayer *contentLayer;
6 @property (nonatomic, readwrite, strong) CALayer *topLayer;
7 @property (nonatomic, readwrite, strong) CALayer *bottomLayer;
8 @property (nonatomic, readwrite, strong) CALayer *leftLayer;
9 @property (nonatomic, readwrite, strong) CALayer *rightLayer;
10 @property (nonatomic, readwrite, strong) CALayer *frontLayer;
11 @property (nonatomic, readwrite, strong) CALayer *backLayer;
12
13 @end
1 #import "BoxTransformViewController.h"
2
3 @implementation BoxTransformViewController
4
5 const CGFloat kSize = 100.;
6 const CGFloat kPanScale = 1./100.;
7
8 - (CALayer *)layerAtX:(CGFloat)x y:(CGFloat)y z:(CGFloat)z
9 color:(UIColor *)color
10 transform:(CATransform3D)transform {
11 CALayer *layer = [CALayer layer];
12 layer.backgroundColor = [color CGColor];
13 layer.bounds = CGRectMake(0, 0, kSize, kSize);
14 layer.position = CGPointMake(x, y);
15 layer.zPosition = z;
16 layer.transform = transform;
17 [self.contentLayer addSublayer:layer];
18 return layer;
19 }
20
21 static CATransform3D MakeSideRotation(CGFloat x, CGFloat y, CGFloat z) {
22 return CATransform3DMakeRotation(M_PI_2, x, y, z);
23 }
24
25 - (void)viewDidLoad {
26 [super viewDidLoad];
27 CATransformLayer *contentLayer = [CATransformLayer layer];
28 contentLayer.frame = self.view.layer.bounds;
29 CGSize size = contentLayer.bounds.size;
30 contentLayer.transform =
31 CATransform3DMakeTranslation(size.width/2, size.height/2, 0);
32 [self.view.layer addSublayer:contentLayer];
33
34 self.contentLayer = contentLayer;
35
36 self.topLayer = [self layerAtX:0 y:-kSize/2 z:0
37 color:[UIColor redColor]
38 transform:MakeSideRotation(1, 0, 0)];
39
40 self.bottomLayer = [self layerAtX:0 y:kSize/2 z:0
41 color:[UIColor greenColor]
42 transform:MakeSideRotation(1, 0, 0)];
43
44 self.rightLayer = [self layerAtX:kSize/2 y:0 z:0
45 color:[UIColor blueColor]
46 transform:MakeSideRotation(0, 1, 0)];
47
48 self.leftLayer = [self layerAtX:-kSize/2 y:0 z:0
49 color:[UIColor cyanColor]
50 transform:MakeSideRotation(0, 1, 0)];
51
52 self.backLayer = [self layerAtX:0 y:0 z:-kSize/2
53 color:[UIColor yellowColor]
54 transform:CATransform3DIdentity];
55
56 self.frontLayer = [self layerAtX:0 y:0 z:kSize/2
57 color:[UIColor magentaColor]
58 transform:CATransform3DIdentity];
59
60 UIGestureRecognizer *g = [[UIPanGestureRecognizer alloc]
61 initWithTarget:self
62 action:@selector(pan:)];
63 [self.view addGestureRecognizer:g];
64 }
65
66 - (void)pan:(UIPanGestureRecognizer *)recognizer {
67 CGPoint translation = [recognizer translationInView:self.view];
68 CATransform3D transform = CATransform3DIdentity;
69 transform = CATransform3DRotate(transform,
70 kPanScale * translation.x,
71 0, 1, 0);
72 transform = CATransform3DRotate(transform,
73 -kPanScale * translation.y,
74 1, 0, 0);
75 self.view.layer.sublayerTransform = transform;
76 }
77
78 @end
它同样实现了立方体的3维旋转效果,但是如果把代码中的
CATransformLayer *contentLayer = [CATransformLayer layer]; 改成 CALayer *contentLayer = [CALayer layer];
旋转的效果将是下面这种,“立方体”成扁平的了。
如果不是因为有CATransformLayer,那么上述代码中的添加立方体的各个面时,用到的zPosition只能用于表示图层的显示顺序,而无法用来决定空间定位。