动画基础--基于Core Animation(2)
参考:https://zsisme.gitbooks.io/ios-/content/
前面的文章动画基础--基于Core Animation(1)提到了图层的基本概念以及可动画参数几何学等知识。
本片文章将继续探讨更加深入的动画知识。
6.视觉效果
圆角
圆角设定可以让原本死板的直角视图更加美观和谐:>
-(void)radiusView { radiusView = [[UIView alloc]initWithFrame:CGRectMake(100.0f, 50.0f, 100.0f, 100.0f)]; radiusView.backgroundColor = [UIColor grayColor]; [self.view addSubview:radiusView]; CALayer *layer = [CALayer layer]; layer.frame = CGRectMake(80.0f, 30.0f, 100.0f, 100.0f); layer.backgroundColor = [UIColor blueColor].CGColor; [radiusView.layer addSublayer:layer]; // 作用于视图的图层 // 1. 设定圆角半径,如果视图本身是一个正方形,此时如果设定半径为其边长一半的时候将会哟圆形效果 radiusView.layer.cornerRadius = 20.0f; // 2. 剪切掉子视图超出父视图的部分 radiusView.layer.masksToBounds = YES; }
结果:
边框:
主要用到图层的
borderWidth:单位为点,默认为0既无边框
borderColor:类型为CGColorRef
边框是绘制在图层边界里面的,而且在所有子内容之前,也在子图层之前。
如下代码我们将masksToBounds设定为NO这样就能清楚的看到边框的子图层的上面。
-(void)radiusViewBorder { radiusView = [[UIView alloc]initWithFrame:CGRectMake(100.0f, 50.0f, 100.0f, 100.0f)]; radiusView.backgroundColor = [UIColor grayColor]; [self.view addSubview:radiusView]; CALayer *layer = [CALayer layer]; layer.frame = CGRectMake(80.0f, 30.0f, 100.0f, 100.0f); layer.backgroundColor = [UIColor blueColor].CGColor; [radiusView.layer addSublayer:layer]; // 作用于视图的图层 // 1. 设定圆角半径,如果视图本身是一个正方形,此时如果设定半径为其边长一半的时候将会哟圆形效果 radiusView.layer.cornerRadius = 20.0f; // 2. 剪切掉子视图超出父视图的部分 radiusView.layer.masksToBounds = NO; radiusView.layer.borderWidth = 5.0f; radiusView.layer.borderColor = [UIColor blackColor].CGColor; }
结果:
阴影
关联四个属性:
shadowOpacity:阴影的透明度,[0.0(不可见),1.0(完全不透明)]
shadowColor:CGColorRef类型,阴影的颜色,默认是黑色。
shadowOffset:属性控制着阴影的方向和距离。CGSize的值,宽度控制这阴影横向的位移,高度控制着纵向的位移。默认值是 {0, -3},
意即阴影相对于Y轴有3个点的向上位移。
shadowRadius:控制着阴影的模糊度,当它的值是0的时候,阴影就和视图一样有一个非常确定的边界线。当值越来越大的时候,
边界线看上去就会越来越摸糊和自然。苹果自家的应用设计更偏向于自然的阴影,所以一个非零值再合适不过了。
例子:
-(void)shadowView { shadowView = [[UIView alloc]initWithFrame:CGRectMake(100.0f, 50.0f, 100.0f, 100.0f)]; shadowView.backgroundColor = [UIColor grayColor]; [self.view addSubview:shadowView]; // 设定阴影 shadowView.layer.shadowOpacity = 1.0f; shadowView.layer.shadowOffset = CGSizeMake(0.0, 5.0); shadowView.layer.shadowRadius = ; // // 1. 设定圆角半径,如果视图本身是一个正方形,此时如果设定半径为其边长一半的时候将会哟圆形效果 // shadowView.layer.cornerRadius = 20.0f; // // // 2. 剪切掉子视图超出父视图的部分 // shadowView.layer.masksToBounds = YES; }
结果:
上述代码中特意将圆角和masksToBounds部分注释掉了,因为masksToBounds设定为true的时候会将图层范围以外的所有东西都切掉,包括阴影:
// 1. 设定圆角半径,如果视图本身是一个正方形,此时如果设定半径为其边长一半的时候将会哟圆形效果 shadowView.layer.cornerRadius = 20.0f; // 2. 剪切掉子视图超出父视图的部分 shadowView.layer.masksToBounds = YES;
结果:
解决方法,我们可以在其底部或者说给他一个相同大小和规格的view来实现阴影:
-(void)shadowAndRadiusView { // 在创建一个空的阴影视图或者图层在shadowView下方,其他参数不重要最主要的是要形状一致即可 shadowViewBottom = [[UIView alloc]initWithFrame:CGRectMake(100.0f, 50.0f, 100.0f, 100.0f)]; shadowViewBottom.backgroundColor = [UIColor whiteColor]; [self.view addSubview:shadowViewBottom]; // 设定阴影 shadowViewBottom.layer.shadowOpacity = 1.0f; shadowViewBottom.layer.shadowOffset = CGSizeMake(0.0, 5.0); shadowViewBottom.layer.shadowRadius = ; shadowViewBottom.layer.cornerRadius = 20.0f; shadowView = [[UIView alloc]initWithFrame:CGRectMake(100.0f, 50.0f, 100.0f, 100.0f)]; shadowView.backgroundColor = [UIColor grayColor]; [self.view addSubview:shadowView]; // 设定阴影 shadowView.layer.shadowOpacity = 1.0f; shadowView.layer.shadowOffset = CGSizeMake(0.0, 5.0); shadowView.layer.shadowRadius = ; // 1. 设定圆角半径,如果视图本身是一个正方形,此时如果设定半径为其边长一半的时候将会哟圆形效果 shadowView.layer.cornerRadius = 20.0f; // 2. 剪切掉子视图超出父视图的部分 shadowView.layer.masksToBounds = YES; }
结果:
特别注意:1.当不设置视图的颜色的时候是无法表现阴影的。2.图层阴影与图层边框不同,图层阴影是根据图层内容进行阴影计算的(本节没有体现)
上述提到图层阴影是根据图层内容来计算得来的,所以所是一个比较耗资源的一个特性,如果我们早知道了图层的阴影表现则科技提前将图层轮廓计算出后直接加载即可
此时我们可以使用到
shadowPath属性
是一个CGPathRef类型(一个指向CGPath的指针)。CGPath是一个Core Graphics对象,用来指定任意的一个矢量图形。我们可以通过这个属性单独于图层形状之外指定阴影的形状。
-(void)shadowPathView { shadowView = [[UIView alloc]initWithFrame:CGRectMake(100.0f, 50.0f, 100.0f, 100.0f)]; shadowView.backgroundColor = [UIColor grayColor]; [self.view addSubview:shadowView]; // 阴影的透明度是必须制定的 shadowView.layer.shadowOpacity = 1.0f; // 创建一个矩形的阴影,除了矩形阴影,还可以创建其他形状的阴影,比如圆形等 CGMutablePathRef squarePath = CGPathCreateMutable(); CGPathAddRect(squarePath, NULL, CGRectMake(,,shadowView.bounds.size.width*, shadowView.bounds.size.height*)); shadowView.layer.shadowPath = squarePath; CGPathRelease(squarePath); }
结果:
7.仿射变换
基础
仿射变换也可以称作为2D变化。UIView的transform与CALayer中的affineTransform相对应他们的类型是CGAffineTransform
,CALayer中的transform是3D变换时候使用的,它的类型是CATransform3D。
当对图层应用变换矩阵,图层矩形内的每一个点都被相应地做变换,从而形成一个新的四边形的形状。CGAffineTransform中的“仿射”的
意思是无论变换矩阵用什么值,图层中平行的两条线在变换之后任然保持平行,CGAffineTransform可以做出任意符合上述标注的变换,图5.2显示了一些仿射的和非仿射的变换:
例子:旋转图层
-(void)affineTransformTestTouch { CGAffineTransform transform = CGAffineTransformMakeRotation(M_PI_4); myTransformView.layer.affineTransform = transform; }
结果:
点击屏幕后视图将会旋转45度。
混合变换
上述讲到了旋转的仿射变换,在2d范围中我们也可以做其他变换,如缩小放大,平移等操作。
同时如果想要几个变换一起实现则我们可以使用混合变换的方式。
混合变换的关键点是将变换首先初始化为一个CGAffineTransformIdentity,它表示什么变化也没有,用于去加载之后的变换。
常用方法:
CGAffineTransformMakeRotation(CGFloat angle) CGAffineTransformMakeScale(CGFloat sx, CGFloat sy) CGAffineTransformMakeTranslation(CGFloat tx, CGFloat ty)
例子:如下图,将视图 先缩小50%,再旋转30度,最后向右移动200个像素
-(void)mixAffineTransformTestTouch { CGAffineTransform transform = CGAffineTransformIdentity; transform = CGAffineTransformScale(transform, 0.5, 0.5);//scale by 50% transform = CGAffineTransformRotate(transform, M_PI / 180.0 * 30.0);//rotate by 30 degrees transform = CGAffineTransformTranslate(transform, , );//translate by 200 points //apply transform to layer myTransformView.layer.affineTransform = transform; }
结果:视图将会按照代码的变换顺序进行变换。
图片向右边发生了平移,但并没有指定距离那么远(200像素),另外它还有点向下发生了平移。原因在于当你按顺序做了变换,上一个变换的结果将会影响之后的变换,所以200像素的向右平移同样也被旋转了30度,缩小了50%,所以它实际上是斜向移动了100像素。这意味着变换的顺序会影响最终的结果,也就是说旋转之后的平移和平移之后的旋转结果可能不同。
8. 3D变换
我们之前介绍过z轴,关于三个坐标轴的定义和围绕它们旋转的方向
参考如下:
与仿射变换中定义的三个常用方法,3D变化也有与之对应的方法:
CATransform3DMakeRotation(CGFloat angle, CGFloat x, CGFloat y, CGFloat z) CATransform3DMakeScale(CGFloat sx, CGFloat sy, CGFloat sz) CATransform3DMakeTranslation(Gloat tx, CGFloat ty, CGFloat tz)
和Core Graphics的函数类似,但是3D的平移和旋转多处了一个z参数,并且旋转函数除了angle之外多出了x,y,z三个参数,分别决定了每个坐标轴方向上的旋转。
例子:将试图按照Y轴旋转45度
-(void)my3DViewTestTouch { CATransform3D transform = CATransform3DMakeRotation(M_PI_4, , , ); my3DView.layer.transform = transform; }
结果:
------------->
问题:
上图中只感觉图片被压缩了,并没有旋转的效果。
原因:
当我们在观察某个物体,当这里物体反转的时候,都是距离远的一侧看上去小一点,距离近的一侧看上去大一点。所以在现实中我们是在一定距离上进行观测的,在程序中我们也需要定义这么一个
观测点,这样的观测在iOS开发中称之为透视投影,反应在属性上则是m34属性,m34的默认值是0,我们可以通过设置m34为-1.0 / d来应用透视效果,d代表了想象中视角相机和屏幕之间的距离,以像素为单位,那应该如何计算这个距离呢?实际上并不需要,大概估算一个就好了。
重写代码:
-(void)my3DViewTestTouch { //初始化一个3D变换 CATransform3D transform = CATransform3DIdentity; // 设定透视距离 transform.m34 = -; // 进行以Y轴旋转变换 transform = CATransform3DRotate(transform, M_PI_4, , , ); // 赋值 my3DView.layer.transform = transform; }
结果:
9.sublayerTransform属性
我理解此属性可以被称之为变换组属性,当父图层(容器图层)设定了某个变换效果的时候,其他子图层就集成了这个变换效果或者参数。如我们可以通过他来设定透视,这样就不必为每一个子视图设定透视了。
总结1:父图层上的sublayerTransform属性只影响其子图层,对于自身无影响
-(void)sublayerTransformTestTouch_1 { //初始化一个3D变换 CATransform3D transform = CATransform3DIdentity; transform.m34 = -; // 进行以Y轴旋转变换 transform = CATransform3DRotate(transform, M_PI_4, , , ); // 容器单独变换,子图层会一起旋转吗? containerView.layer.sublayerTransform = transform; }
结果:
总结2:父图层上的transform属性的变换场景时子图层将跟随一起变换。
-(void)sublayerTransformTestTouch_1 { //初始化一个3D变换 CATransform3D transform = CATransform3DIdentity; transform.m34 = -; // 进行以Y轴旋转变换 transform = CATransform3DRotate(transform, M_PI_4, , , ); // 容器单独变换,子图层会一起旋转吗? //containerView.layer.sublayerTransform = transform; containerView.layer.transform = transform; }
结果:
总结3.sublayerTransform属性可以灭点统一(除了统一灭点外,可以通过这个属性进行m34的透视距离等进行子视图的统一设定,而不需要分别对于子视图进行设定)
何为灭点:
当不设定sublayerTransform属性的时候,子图层的灭点都是其锚点,如下代码:
-(void)sublayerTransformTestTouch_1 { //初始化一个3D变换 CATransform3D transform = CATransform3DIdentity; transform.m34 = -; // 设置与transform containerView.layer.transform = transform; // 某个子图层单独变换 leftView.layer.transform = CATransform3DMakeRotation(M_PI_2, , , ); RightView.layer.transform = CATransform3DMakeRotation(M_PI_2, , , ); }
上图中我们分别将子图层反转90度,结果:
由于灭点都是在子图层自身的锚点,所以当旋转90后,由于图层又是无厚度的,所以看起来像是消失饿一样。
当设定sublayerTransform的时候,以为着,其子图层将统一灭点统一到了容器图层的锚点,这样预想即使旋转90,由于灭点的关系,子图层也不会“消失”
-(void)sublayerTransformTestTouch_1 { //初始化一个3D变换 CATransform3D transform = CATransform3DIdentity; transform.m34 = -; // 设置与transform //containerView.layer.transform = transform; // 设定了 containerView.layer.sublayerTransform = transform; // 某个子图层单独变换 leftView.layer.transform = CATransform3DMakeRotation(M_PI_2, , , ); RightView.layer.transform = CATransform3DMakeRotation(M_PI_2, , , ); }
结果:
以上。
动画基础--基于Core Animation(2)的更多相关文章
- 动画基础--基于Core Animation(3)
参考:https://zsisme.gitbooks.io/ios-/content/ 前面的文章动画基础--基于Core Animation(1),动画基础--基于Core Animation(2) ...
- 动画基础--基于Core Animation(1)
1.简介 上一篇文章[New learn]动画-基于UIView了解到了一些直接由UIView这个在UIKIT提供的类中提供的一些动画方法. 使用UIView的动画特性已经能够满足我们很多的需求,它是 ...
- iOS 动画效果:Core Animation & Facebook's pop
本文转载至 http://www.cocoachina.com/ios/20151223/14739.html 感谢原创作者分享 前言相信很多人对实现 iOS 中的动画效果都特别头疼,往往懒得动手,功 ...
- iOS 动画篇 之 Core Animation (一)
iOS中实现动画有两种方式,一种是自己不断的通过drawRect:方法来绘制,另外一种就是使用核心动画(Core Animation). 导语: 核心动画提供高帧速率和流畅的动画,而不会增加CPU的负 ...
- Expression Blend实例中文教程(7) - 动画基础快速入门Animation
通过前面文章学习,已经对Blend的开发界面,以及控件有了初步的认识.本文将讲述Blend的一个核心功能,动画设计.大家也许注意到,从开篇到现在,所有的文章都是属于快速入门,是因为这些文章,都是我曾经 ...
- 转 iOS Core Animation 动画 入门学习(一)基础
iOS Core Animation 动画 入门学习(一)基础 reference:https://developer.apple.com/library/ios/documentation/Coco ...
- iOS Core Animation 动画 入门学习(一)基础
reference:https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/CoreAnimation_guide ...
- IOS动画(Core Animation)总结 (参考多方文章)
一.简介 iOS 动画主要是指Core Animation框架.官方使用文档地址为:Core Animation Guide. Core Animation是IOS和OS X平台上负责图形渲染与动画的 ...
- Core Animation 动画
Core Animation框架 Core Animation可以作用与动画视图或者其他可视元素,为你完成了动画所需的大部分绘帧工作.你只需要配置少量的动画参数(如开始点的位置和结束点的位置)即可使用 ...
随机推荐
- [洛谷P5107]能量采集
题目大意:有一张$n(n\leqslant50)$个点$m(m\leqslant n(n-1))$条边的有向图,每个点还有一个自环,每个点有一个权值.每一秒钟,每个点的权值会等分成出边个数,流向出边. ...
- BZOJ5340 & 洛谷4564 & LOJ2552:[CTSC2018]假面——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=5340 https://www.luogu.org/problemnew/show/P4564 ht ...
- BZOJ1014:[JSOI2008]火星人prefix——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=1014 Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样 ...
- CentOS 6.5 下 QT4 连接 mysql 数据库的步骤
QT4 的安装请参考: CentOS 6.5 下安装 QT 4 mysql 的安装请参考: CentOS 6.5 下安装配置 mysql 1. 预防万一,先安装一下mysql-devel(一定要装!) ...
- was(websphere application server)中用apache的httpclient时jar包冲突问题的解决
这个问题可以用was的共享库解决. 具体解决方案如下图所示: 对于有多个jar包冲突时,为每个冲突的jar包都新建一个共享库即可. 我之前的错误操作是以为一个共享库可以添加多个冲突的jar包用分号和逗 ...
- boost文件锁的使用
boost中可以用boost::interprocess::file_lock类对文件进行加锁和解锁操作. #include <fstream> #include <iostream ...
- Leetcode 295. 数据流的中位数
1.题目要求 中位数是有序列表中间的数.如果列表长度是偶数,中位数则是中间两个数的平均值. 例如, [2,3,4] 的中位数是 3 [2,3] 的中位数是 (2 + 3) / 2 = 2.5 设计一个 ...
- c# 定时执行任务
在Global.asax文件中加上 void Application_Start(object sender, EventArgs e) { // Code that runs on applicat ...
- Maven命令行窗口指定settings.xml
maven命令行窗口指定特定settings.xml 在命令行界面指定settings.xml,命令如下: mvn install --settings c:\user\settings.xml 例如 ...
- vue-cli中引入jquery的方法
vue-cli中引入jquery的方法 以前写vue项目都没有引入过jquery,今天群里面的一位小伙伴问了我这个问题,我就自己捣鼓了一下,方法如下: 我们先进入webpack.base.conf.j ...