第四篇:CALayer能力之仿射变换和3D变换

2018-01-22  本文已影响51人  意一ineyee

目录

一、UIView的仿射变换

1、单仿射变换
2、混合仿射变换
3、CGAffineTransformIdentity

二、CALayer的仿射变换

三、CALayer的3D变换

1、单3D变换
2、混合3D变换
3、CATransform3DIdentity
4、3D变换其它

概述:

一、UIView的仿射变换

1、单仿射变换

单仿射变换是指只对视图做某一种类型的变换,平移或者旋转或者缩放。因为view的transform仅仅是一个属性,它只会记录我们最后一个给它赋值的变换类型,所以如果想要实现变换的组合就需要使用下面的混合仿射变换。

单仿射变换针对平移、旋转、缩放提供了三个方法,如下:

举例如下:

self.redView = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
self.redView.backgroundColor = [UIColor redColor];
[self.view addSubview:self.redView];

// 平移
self.redView.transform = CGAffineTransformMakeTranslation(100, 100);
// 旋转
self.redView.transform = CGAffineTransformMakeRotation(M_PI_4);
// 缩放
self.redView.transform = CGAffineTransformMakeScale(2, 2);
2、混合仿射变换

有的时候我们想对一个视图进行多个变换的组合,那么使用单仿射变换是实现不了的,需要用到混合仿射变换。所谓混合仿射变换,是指我们可以在一个仿射变换的基础上再添加另一个仿射变换。但是需要注意,即便混合仿射变换的组合一样,顺序不一样也会造成不一样的变换效果(比方说先旋转后缩放和先缩放后旋转效果有可能不一样)

混合仿射变换针对平移、旋转、缩放提供了三个方法,如下:

举例如下:

self.redView = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
self.redView.backgroundColor = [UIColor redColor];
[self.view addSubview:self.redView];

// 初始化一个什么都不做的变换
CGAffineTransform transform = CGAffineTransformIdentity;
// 先平移
transform = CGAffineTransformTranslate(transform, 100, 100);
// 后旋转
transform = CGAffineTransformRotate(transform, M_PI_4);
// 再缩放
transform = CGAffineTransformScale(transform, 2, 2);

self.redView.transform = transform;
3、CGAffineTransformIdentity

此外仿射变换还提供了CGAffineTransformIdentity来表征一个什么都不做的变换

这样就为单仿射变换和混合仿射变换提供了一个桥梁,只要混合仿射变换的基础变换传入这个什么都不做的变换,就变成了单仿射变换。

二、CALayer的仿射变换

前面说了UIView的仿射变换只是对CALayer的仿射变换做了一层封装,所以CALayer的仿射变换和UIView的操作几乎一模一样,所以CALayer的仿射变换就不多做介绍了。

只是view用来做仿射变换的属性叫transform,而layer的transform属性是用来做3D变换的,所以layer用来做仿射变换的属性换成了affineTransform,其它的完全一样。

三、CALayer的3D变换

声明:

1、单3D变换

单3D变换针对平移、旋转、缩放提供了三个方法,如下:

我们以3D旋转为例:

// 我们以旋转为例:
UIView *sourceView = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
sourceView.backgroundColor = [UIColor redColor];
[self.view addSubview:sourceView];

self.redView = [[UIView alloc] initWithFrame:CGRectMake(100, 250, 100, 100)];
self.redView.backgroundColor = [UIColor redColor];
[self.view addSubview:self.redView];

// 绕X轴旋转45度
self.redView.layer.transform = CATransform3DMakeRotation(M_PI_4, 1, 0, 0);
1.png

可以看到绕X轴旋转看起来好像没有旋转仅仅是竖向压缩了一点(绕Y轴旋转也是同理),是不是出错了?不是,是因为我们没有模拟现实场景做透视投影的处理,所以看起来好像出错了。

透视投影

如果我们直接使用CATransform3DMakeRotation(..., ..., ..., ...);会发现无论是绕X轴还是绕Y轴旋转,结果都好像是压缩了一样,而没有旋转变换的效果。

其实是进行了旋转变换的,只是因为所有的点都进行了同样的变换,所以原来平行的边还是平行的。而在实际中,经过旋转之后原理我们的那条边应该会看起来短一些,靠近我们的边会看起来长一些。

所以我们在进行3D旋转时为了达到更模拟实际的透视效果就不能直接使用CAransform3DMakeRotation(..., ..., ..., ...),而是使用组合3D变换的旋转CATransform3DRotate(..., ..., ..., ..., ...),并且设置transform.m34 = - 1.0 / 500.0;来达到远边短近边长的透视效果。修改代码如下:

// 我们以旋转为例:
UIView *sourceView = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
sourceView.backgroundColor = [UIColor redColor];
[self.view addSubview:sourceView];

self.redView = [[UIView alloc] initWithFrame:CGRectMake(100, 250, 100, 100)];
self.redView.backgroundColor = [UIColor redColor];
[self.view addSubview:self.redView];

CATransform3D transform = CATransform3DIdentity;
// 绕X轴旋转45度 + 透视效果
transform.m34 = - 1.0 / 500;
transform = CATransform3DRotate(transform, M_PI_4, 1, 0, 0);
self.redView.layer.transform = transform;
1.png

可以发现,远离我们的边比较短了,达到了效果。

2、混合3D变换

同样的,3D变换也可以组合,类似于组合仿射变换,针对平移、旋转、缩放提供了如下方法:

3、CATransform3DIdentity

此外3D变换也提供了CATransform3DIdentity来表征一个什么都不做的变换,这样只要混合3D变换的基础变换只要传入这个什么都不做的变换,就变成了单3D变换。

4、3D变换其它

此外,3D变换还有很多其它需要注意和好玩的地方,如灭点(就是一个视图的一个边无限远离我们时,那条边就会缩成一个点,我们称之为灭点,要想达到这样模拟真实的效果,就需要注意)、绘制立方体等等,如果需要可深入学习。

上一篇 下一篇

猜你喜欢

热点阅读