时隔三天后,各位终于等到我的更新了.今天我的主题是如何在图层上实现三维变形.
在UIView上,我们可以使用CGAffineTransform来对视图进行:平移(translation),旋转(Rotation),缩放(scale),倾斜(Invert)操作,但这些操作是没有动态立体效果的, 这只能称为二维变形.而在图层中,我们可以使用CATransform3D进行"视角旋转"来完成三维变形的效果,但这常称为2.5D,而非真正意义上的3D,因为他不能让图层真正成为三维对象,而只是模拟出三维的动画效果.
请看三维动画效果:
下面我就来一步一步的来实现它.
1.从图中的显示效果来看,我们需要创建六个图层,来表示一个立体图形六个不同的面.并且创建一个CATransformLayer类来作为容器:
/**底部容器*/
@property (nonatomic,strong) CATransformLayer *contentLayer;
/**上面*/
@property (nonatomic,strong) CALayer *topLayer;
/**下面*/
@property (nonatomic,strong) CALayer *bottomLayer;
/**左面*/
@property (nonatomic,strong) CALayer *leftLayer;
/**右面*/
@property (nonatomic,strong) CALayer *rightLayer;
/**前面*/
@property (nonatomic,strong) CALayer *frontLayer;
/**后面*/
@property (nonatomic,strong) CALayer *backLayer;
通常情况下,像这种批量创建对象的工作,不要做傻傻的码农,要学会封装,这样我们只需要传入图层所必须的变量参数就可以创建一个图层了.
- (CALayer *)layerAtX:(CGFloat)x y:(CGFloat)y z:(CGFloat)z color:(UIColor *)color transform:(CATransform3D)transform{
CALayer *layer = [CALayer layer];
layer.backgroundColor = color.CGColor;
layer.bounds = CGRectMake(0, 0, 100, 100);
layer.position = CGPointMake(x, y);
layer.zPosition = z;
layer.transform = transform;
[self.contentLayer addSublayer:layer];
return layer;
}
其中,我要说一下上面代码中layer的zPosition与transfrom属性,在这个例子中,我会使用CATransformLayer类,这个类是CALayer的子类,在官方文档上有一句话是这么描述的"CATransformlayer objects are used to create sure 3D layer hierarchies".那他到底和CALayer有什么区别呢?是这样的.在CALayer中的zPosition属性,如果只使用CALayer,那么zPosition只能用于计算图层的显示顺序,这样会使图形看起来是扁平的.而在CATransformLayer这个类当中,zPosition就可以用来决定空间位置.他会让图形的position不限于X,Y轴上,也可以在Z轴上设置相应值来让图形添加景深,从而让图形具有立体效果.所以,x,y,z分别是X轴,Y轴,Z轴方向的值.
下面说说本文的核心部分:CALayer的transfrom属性:这个属性主要是操作CATranfrom3D类对图层进行三维变形.在我们这个例子中,主要是对图层进行旋转,所以着重讲一下CATranfrom3D类当中进行3D旋转的方法:
CA_EXTERN CATransform3D CATransform3DMakeRotation (CGFloat angle, CGFloat x,
CGFloat y, CGFloat z)
可以看出来,这是一个c语言封装好的函数,里面的参数我来说明:第一个参数:里面的角度是图层需要旋转的角度,是以弧度为单位,我列举一下几个常用的:M_PI是表示180度,M_PI_2表示90度,M_PI_4表示45度.后面的三个参数x,y,z:我们知道,在二维形变中,旋转效果是围绕着一个点进行变化的,而在三维变化中,却是围绕着一条轴.而这三个参数在立体平面中的坐标系中确定一个点,这个点与圆点(左上角)的连线确定一条轴,我举一个特殊的例子:比如绕着y轴旋转45度?绕着y轴旋转,那么必然这三个参数确定的点在Y轴上,在Y轴上,那么其他值必然为0,所以里面的参数应该这样填:CATransform3DMakeRotation (M_PI_4, 0, 1, 0);
好了,那么现在初始化CATransformLayer,然后将六个图层添加到这个容器中.
// 创建CATransformLayer对象
CATransformLayer *contentLayer = [CATransformLayer layer];
contentLayer.frame =self.view.layer.bounds;
CGSize size = contentLayer.bounds.size;
contentLayer.transform = CATransform3DMakeTranslation(size.width / 2, size.height / 2, 0);
self.contentLayer = contentLayer;
[self.view.layer addSublayer:contentLayer];
// 初始化六个图层
// 顶部与底部的沿着x轴旋转90度
self.topLayer = [self layerAtX:0 y:-kSize/2 z:0 color:[UIColor redColor] transform:CATransform3DMakeRotation(M_PI_2, 1, 0, 0)];
self.bottomLayer = [self layerAtX:0 y:kSize/2 z:0 color:[UIColor greenColor] transform:CATransform3DMakeRotation(M_PI_2, 1, 0, 0)];
// 左边与右边的沿着y轴旋转90度
self.leftLayer = [self layerAtX:-kSize / 2 y:0 z:0 color:[UIColor blueColor] transform:CATransform3DMakeRotation(M_PI_2, 0, 1, 0)];
self.rightLayer = [self layerAtX:kSize/2 y:0 z:0 color:[UIColor blackColor] transform:CATransform3DMakeRotation(M_PI_2, 0, 1, 0)];
// 前面与后面的不需要变化,所以使用CATransform3DIdentity
self.frontLayer = [self layerAtX:0 y:0 z:kSize / 2 color:[UIColor brownColor] transform:CATransform3DIdentity];
self.backLayer = [self layerAtX:0 y:0 z:-kSize / 2 color:[UIColor brownColor] transform:CATransform3DIdentity];
说明一点:kSize 是我定义的一个宏,表示的是这个正方体的边长.
现在的视图上显示的是什么效果呢
为什么只显示前面图层给的brownColor呢?这就是对的,由于旋转90度后,上下与左右都收在前面图层的四侧,与视图垂直,所以我们看不到,那么我就给一个pan手势,随着手指的移动,旋转这个立体图形.
- (void)pan:(UIPanGestureRecognizer *)recognizer{
//获取到的是手指移动后,在相对坐标中的偏移量(以手指接触屏幕的第一个点为坐标原点)
CGPoint translation = [recognizer translationInView:self.view];
CATransform3D transform = CATransform3DIdentity;
transform = CATransform3DRotate(transform, translation.x * 1 / 100, 0, 1, 0);
transform = CATransform3DRotate(transform, translation.y * - 1 / 100, 1, 0, 0);
self.view.layer.sublayerTransform = transform;
}
结束语:可能有些读者对图层相关知识不太熟悉的看起来会有些吃力,不好理解.如果有需要的话,请将您的邮箱发在我的评论里面,我会将demo奉上.我呢,水平有限,能力一般,在文章中如果有知识点的疏漏或错误,还望告知,希望能与各位iOS开发爱好者共同学习进步.