iOS核心动画高级技巧之图层变换和专用图层(二)

  仿射变换

  iOS仿射变换是CGAffineTransform,仿射变换的特点是变换后的图形对边依然是平行的,它包括 CGAffineTransformMakeRotation(CGFloat angle) / CGAffineTransformMakeScale(CGFloat sx, CGFloat sy) / CGAffineTransformMakeTranslation(CGFloat tx, CGFloat ty),直接看代码

 1 blueView = UIView()
 2 blueView.frame = CGRectMake(50, 100, 100, 100)
 3 blueView.backgroundColor = UIColor.blueColor()
 4 self.view.addSubview(blueView)
 5
 6 yellowView = UIView()
 7 yellowView.frame = CGRectMake(50 + 200 / 1.414, 100, 100, 100)//注意yellowView的水平位置,和blueView作对比
 8 yellowView.backgroundColor = UIColor.yellowColor()
 9 self.view.addSubview(yellowView)
10
11 blueView.transform = CGAffineTransformIdentity  //初始化transform
12 blueView.transform = CGAffineTransformMakeScale(0.5, 0.5 )  //缩小0.5倍
13 blueView.transform = CGAffineTransformRotate(blueView.transform, CGFloat(M_PI_4))   //旋转pi/4
14 blueView.transform = CGAffineTransformTranslate(blueView.transform, 400, 0) //平移400

   这里只需要注意transform的叠加互相之间是有影响的,blueView缩小了0.5倍和旋转了45°,所以本来应该在水平位置上平移400的最后在45°方向平移了200,所以在水平方向平移的距离大约是200/1.414,和yellowView形成对比.

  3D变换

  3D变换和仿射变换不同,虽然它也是乘以一个二维向量,但是它是4x4的二维向量,而仿射变换是2x3的向量,而且3D变换可以通过直接改变向量的单个的值来设置向量,比如transform.m11 / transform.m44 对应的就是向量上对应位置的值,由于是3维空间的变换,所以有些不同,仿射的旋转等价于3D变换的Z轴旋转,它的x,y的组合向量可以使它向倾斜的角度(如45°)旋转,而平移忽略掉Z轴上的就是一样的,缩放也是忽略掉Z轴上的就行.而由于是3D变换缩放会使平移缩放对应比例,而x/y/z轴的旋转都不会使它的方向改变,这是由于矩阵的值表示的范围广,不会互相影响.

1 blueLayer.transform = CATransform3DIdentity  //初始化transform
2 blueLayer.transform = CATransform3DMakeScale(0.5, 0.5, 0)  //缩小0.5倍
3 blueLayer.transform = CATransform3DRotate(blueLayer.transform,CGFloat( M_PI_4 ), 0.0,  1.0, 0) //旋转pi/4
4 blueLayer.transform = CATransform3DTranslate(blueLayer.transform,400, 0, 0)     //平移400

  由于3D变换分成多个方向的,所以沿X或Y方向的旋转就像缩放了一样,可以通过设置向量对应的值来修复这个效果,让它看上去更真实一点,结果它会有一个倾斜角度,有一个投影效果,这样当你做平移的时候会改变显示的大小,所以一般不要一起用了,而要让这个效果有效,需要在初始化transform时就设置m34的值(这个值最好在-1/500.0 到 -1/5000.0之间),放到后面没有效果,在后面也不能用scale放大缩小,不然会覆盖这个值.所以这个效果基本是单独拿出来显示效果的.

1 var transform = CATransform3DIdentity //初始化transform
2 transform.m34 = -1 / 500.0 //设置m34的值
3 // transform = CATransform3DScale( transform, 0.5, 0.5, 0) //缩小0.5倍,这里不能用
4 transform = CATransform3DRotate(transform,CGFloat( M_PI_4 ), 0.0,  1.0, 0) //旋转pi/4
5 transform = CATransform3DTranslate(transform,400, 0, 0)     //平移400
6 blueLayer.transform = transform

  当你在投射的方向平移足够大的距离,它最后的成像就是一个点了,这个点一般是图层的anchorPoint点,如果是一个图层的好几个子图层都需要这种效果,那么直接设置它的父图层transform的m34为-1/ 500.0 然后设置它的sublayerTransform属性,当设置它的子layer的rotote属性那个子layer就会有对应的投射效果. 如:outLayer.sublayerTransform = outLayer.transform

  如果旋转180°从背面去看layer,layer会显示出和layer对称的的图片,因为layer是双面绘制的,但如果有文字就会看起来很混乱并且浪费GPU资源,所以最好能够禁用它,而layer提供了这个属性:doubleSided,值为true双面为false则为单面.

  内外层layer的选择可以相互叠加和抵消,这个在Z轴上的旋转是可以的,但是在X/Y上并不是这样的,是由于它们并不处于同一个3D空间内,同时需要注意的是,如果使用m34这个特殊的向量值做投影,每次先给一个transform初始化为CATransform3DIdentity,然后直接设置m34的值然后做旋转等,再赋值给layer的transform

  专用图层

CAShapeLayer

  CAShapeLayer 是专门用来绘画形状的layer,它对比画图有很大的优势,它使用了硬件加速,所以绘图速度很快,它不需要寄宿图片所以不会使用太多内存,它也不会和普通图层一样被裁剪掉,而且它不会被像素化,最后就不会模糊.你可以设置lineWith(线宽,用点表示单位)/ lineCap(线条结尾的样子)和lineJoin(线条之间的结合点的样子),但是只有一次设置的机会.CAShapeLayer还可以单独设置圆角,下面是代码和对应的两个运行效果,前面一个线条的人另一个是3个圆角的直角矩形.

DEMO1: 1 let shapePath = UIBezierPath()
 2 shapePath.moveToPoint(CGPointMake(175, 100))
 3 shapePath.addArcWithCenter(CGPointMake(150, 100), radius: 25, startAngle: 0, endAngle:CGFloat( 2 * M_PI ), clockwise: true)
 4 shapePath.moveToPoint(CGPointMake(150, 125))
 5 shapePath.addLineToPoint(CGPointMake(150, 175))
 6 shapePath.addLineToPoint(CGPointMake(125, 225))
 7 shapePath.moveToPoint(CGPointMake(150, 175))
 8 shapePath.addLineToPoint(CGPointMake(175, 225))
 9 shapePath.moveToPoint(CGPointMake(100, 150))
10 shapePath.addLineToPoint(CGPointMake(200, 150))
11
12 let shapeLayer = CAShapeLayer()
13 shapeLayer.strokeColor = UIColor.redColor().CGColor
14 shapeLayer.fillColor = UIColor.clearColor().CGColor
15 shapeLayer.lineWidth = 5
16 shapeLayer.lineJoin = kCALineJoinRound
17 shapeLayer.lineCap = kCALineCapRound
18 shapeLayer.path = shapePath.CGPath
19 self.view.layer.addSublayer(shapeLayer)
DEMO2:1 var rect = CGRectMake(50, 50, 100, 100);
2 var radii = CGSizeMake(20, 20);
3 var corners = UIRectCorner.TopRight | UIRectCorner.BottomRight | UIRectCorner.BottomLeft
4 var shapePath = UIBezierPath(roundedRect: rect, byRoundingCorners: corners, cornerRadii: radii) 

CATextLayer

  可以在layer中直接用Core Graphics直接写入文字,这就是UILabel的实现方式,如果直接在图层上记录文本将是一件很麻烦的事,iOS提供了CATextLayer来实现layer上显示文本,它本身使用了Core text ,渲染速度很快.

 1 var textLayer = CATextLayer()
 2 textLayer.frame = CGRectMake(100, 100, 200, 300)
 3 self.view.layer.addSublayer(textLayer)
 4
 5 //设置它的属性
 6 textLayer.foregroundColor = UIColor.redColor().CGColor
 7 textLayer.alignmentMode = kCAAlignmentJustified
 8 textLayer.wrapped = true
 9
10 //它的font是CGFont类型,需要大小字体分开设置
11 var font = UIFont.systemFontOfSize(24)
12 textLayer.font = CGFontCreateWithFontName(font.fontName)
13 textLayer.fontSize = font.pointSize
14
15 var textStr = "hello kitty hi nohhhh no wo  shi lllll aaaaawo  jiojhello kitty hi nohhhh no wo  shi lllll aaaaawo  jioj"
16 textLayer.string = textStr
17
18 //它contentScale默认是1,为了让它以retina的质量来显示,设置为2
19 textLayer.contentsScale = UIScreen.mainScreen().scale

   这里也可以用NSAttributedString富文本,但是由于swift类型转换的问题挺麻烦的,不写demo了.

CATransformLayer

  这个图层类解决了图层间的层级关系,如下面这个demo所示:如果是CALayer旋转就没有层级,如果是CATransformLayer,它就有了层级

 1 //outLayer = CALayer()
 2 outLayer = CATransformLayer() //如果是上面这个普通的CALayer它如果旋转就不会有双层的效果
 3
 4
 5 outLayer.frame = CGRectMake(50, 50, 300, 300)
 6 outLayer.backgroundColor = UIColor.grayColor().CGColor
 7 self.view.layer.addSublayer(outLayer)
 8
 9 var transform = CATransform3DIdentity //初始化transform
10 transform.m34 = -1 / 500.0 //设置m34的值
11 transform = CATransform3DRotate(transform,CGFloat( M_PI_2 ), 0.0,  1.0, 0) //旋转pi/4
12 outLayer.transform = transform
13
14 //outLayer.sublayerTransform = transform
15
16
17 blueLayer = CALayer()
18 blueLayer.frame = CGRectMake(50, 50, 200, 200)
19 blueLayer.backgroundColor = UIColor.blueColor().CGColor
20 outLayer.addSublayer(blueLayer)
21
22
23 var blueLayerTransform = CATransform3DIdentity;
24 blueLayerTransform  = CATransform3DTranslate(blueLayerTransform, 0, 0, 50);
25 blueLayer.transform = blueLayerTransform;
26
27 redLayer = CALayer()
28 redLayer.frame = CGRectMake(50, 50, 200, 200)
29 redLayer.backgroundColor = UIColor.redColor().CGColor
30 outLayer.addSublayer(redLayer)
31
32 var fromValue = CATransform3DIdentity
33 fromValue.m34 = -1 / 500.0
34 fromValue = CATransform3DRotate(fromValue, 0, 0, 1, 0)
35
36 var toValue = CATransform3DIdentity
37 toValue.m34 = -1 / 500.0
38 toValue = CATransform3DRotate(toValue, CGFloat( M_PI ), 0, 1, 0)
39
40 var basicAnimation = CABasicAnimation(keyPath: "transform")
41 basicAnimation.duration = 1.0
42 basicAnimation.fromValue = NSValue(CATransform3D:fromValue)
43 basicAnimation.toValue = NSValue(CATransform3D:toValue)
44 outLayer.transform = toValue
45 outLayer.addAnimation(basicAnimation, forKey: "transform3D")

CAGradientLayer

  CAGradientLayer它主要是可以设置渐变色,通过colors属性和,startPoint和endPoint设置过渡颜色和位置,这时候设置背景色是没有用的

1 gradientLayer = CAGradientLayer()
2 gradientLayer.frame = CGRectMake(50, 50, 300, 300)
3 gradientLayer.backgroundColor = UIColor.grayColor().CGColor
4 self.view.layer.addSublayer(gradientLayer)
5
6 gradientLayer.colors = [UIColor.redColor().CGColor,UIColor.blueColor().CGColor, UIColor.greenColor().CGColor]
7 gradientLayer.startPoint = CGPointMake(0, 0)
8 gradientLayer.endPoint = CGPointMake(1, 1)

   它还有一个locations属性,可以设置每个渐变色的间距,这个数组的长度需要和colors数组的长度相同,location的值是按endPoint的值来说的,不是是多少及时多少

CAReplicatorLayer

  CAReplicatorLayer可以使用在需要创建多个同样的layer只是轨迹颜色有规则的变化的时候,它会把它的子图层有规律的重复展示出来,而可以设置它重复的次数/每次渐变的颜色递增递减值/每次transform变换的路径.

 1 repeatLayer = CAReplicatorLayer()
 2 repeatLayer.frame = CGRectMake(50, 50, 300, 300)
 3 repeatLayer.backgroundColor = UIColor.grayColor().CGColor
 4 self.view.layer.addSublayer(repeatLayer)
 5
 6 var transform = CATransform3DIdentity
 7 transform = CATransform3DTranslate(transform, 0, 100, 0);
 8 transform = CATransform3DRotate(transform, CGFloat( M_PI / 5.0 ), 0, 0, 1);
 9 transform = CATransform3DTranslate(transform, 0, -100, 0);
10 repeatLayer.instanceTransform = transform;
11
12 repeatLayer.instanceCount = 10
13
14 repeatLayer.instanceBlueOffset = -0.1
15 repeatLayer.instanceRedOffset = -0.1
16
17 var layer  = CALayer()
18 layer.frame = CGRect(x: 125, y: 125, width: 50, height: 50)
19 layer.backgroundColor = UIColor.whiteColor().CGColor
20 repeatLayer.addSublayer(layer) 

  它最后的结果就是一圈颜色递变的正方形,它可以做动画中一个飞机的路径等效果.它的一个重要实际用处就是做倒影,因为如果做图层的复制的话,倒影不可能跟着原layer做实时更新,而CAReplicatorLayer就可以做到.

 1 reflectionLayer = CAReplicatorLayer()
 2 var img = UIImage(named: "3333.jpg")
 3 reflectionLayer.frame = CGRectMake((self.view.bounds.size.width - img!.size.width) / 2 , 100, img!.size.width, img!.size.height * 1.5)
 4 reflectionLayer.backgroundColor = UIColor.grayColor().CGColor
 5 self.view.layer.addSublayer(reflectionLayer)
 6
 7 var transform = CATransform3DIdentity
 8 transform = CATransform3DScale(transform, 1, -0.5, 1);
 9 transform = CATransform3DTranslate(transform, 0, -img!.size.height * 3 / 4 + 2, 0.0);
10 reflectionLayer.instanceTransform = transform;
11
12 reflectionLayer.instanceCount = 2
13
14 var imageLayer  = CALayer()
15 imageLayer.frame = CGRect(x: 0, y: 0, width: img!.size.width, height: img!.size.height)
16 imageLayer.backgroundColor = UIColor.whiteColor().CGColor
17 imageLayer.contents = img!.CGImage
18 //layer.anchorPoint = CGPointMake(0, 0)
19 reflectionLayer.addSublayer(imageLayer)
20
21 //设置透明度,在外面用个层来设置
22 var gradientLayer = CAGradientLayer()
23 gradientLayer.colors = [UIColor.whiteColor().colorWithAlphaComponent(0.2).CGColor, UIColor.whiteColor().CGColor]
24 gradientLayer.frame = CGRectMake(reflectionLayer.frame.origin.x , reflectionLayer.frame.origin.y + reflectionLayer.frame.size.height / 3.0 * 2, reflectionLayer.frame.size.width, reflectionLayer.frame.size.height / 2)
25 self.view.layer.addSublayer(gradientLayer)
26
27
28 //设置文字
29 var textLayer = CATextLayer()
30 textLayer.frame = CGRectMake(80, 50, 200, 300)
31 self.view.layer.addSublayer(textLayer)
32
33 //设置它的属性
34 textLayer.foregroundColor = UIColor.redColor().CGColor
35 textLayer.alignmentMode = kCAAlignmentJustified
36 textLayer.wrapped = true
37
38 //它的font是CGFont类型,需要大小字体分开设置
39 var font = UIFont.systemFontOfSize(24)
40 textLayer.font = CGFontCreateWithFontName(font.fontName)
41 textLayer.fontSize = font.pointSize
42
43 var textStr = "What a fuck!"
44 textLayer.string = textStr
45
46 //它contentScale默认是1,为了让它以retina的质量来显示,设置为2
47 textLayer.contentsScale = UIScreen.mainScreen().scale
48
49 imageLayer.addSublayer(textLayer)
50
51
52 var basicAnimation = CABasicAnimation(keyPath: "position.y")
53 basicAnimation.duration = 2.0
54 basicAnimation.fromValue =  Float( textLayer.position.y  )
55 var toValue:Float = Float( textLayer.position.y  + 100.0)
56 basicAnimation.toValue = NSNumber(float: toValue)
57 basicAnimation.removedOnCompletion = true
58 basicAnimation.fillMode = kCAFillModeForwards
59 textLayer.addAnimation(basicAnimation, forKey: nil)
60
61 // textLayer.frame.origin.y = CGFloat( toValue)
62 textLayer.position = CGPointMake(textLayer.position.x, textLayer.position.y  + 100.0)

CAScrollLayer

  CAScrollLayer和UIScrollView类似,它和CALayer相比多了个scrollPoint的方法,如果要用这个方法可以使用CAScrollLayer

1 NSTimer.scheduledTimerWithTimeInterval(2, target: self, selector: NSSelectorFromString("setPosition"), userInfo: nil, repeats: false)
2
3 func setPosition () {
4     self.scrollLayer.scrollToPoint(CGPointMake(0, 100))
5 }

CATiledLayer

  CATiledLayer的可以做到图片/PDF等的分割显示,如果一个一张图片分辨率超过2048*2048(因平台不同),超过了OpenGL最大纹理尺寸,所以会有性能问题,一个PDF一般也比较大,所以容易出现性能问题(后面会单独写一个demo)

CAEmitterLayer

  CAEmitterLayer能模仿粒子反射,如果火焰等,能控制粒子颜色/放射的速率,透明度,方向,个数等.

 1 emitterLayer = CAEmitterLayer()
 2 emitterLayer.frame = CGRectMake(100 , 100, 200, 200)
 3 emitterLayer.backgroundColor = UIColor.grayColor().CGColor
 4 self.view.layer.addSublayer(emitterLayer)
 5
 6 emitterLayer.renderMode = kCAEmitterLayerAdditive
 7 emitterLayer.emitterPosition = CGPointMake(emitterLayer.frame.size.width / 2, emitterLayer.frame.size.height / 2)
 8
 9 var cell = CAEmitterCell()
10 cell.contents = UIImage(named: "lizi.png")?.CGImage
11 cell.birthRate = 10 //粒子出现的速率
12 cell.lifetime = 4.0 //声明周期,秒
13 cell.emissionRange = 2 //发射的方向
14
15 cell.color = UIColor(red: 1, green: 1, blue: 0.5, alpha: 1).CGColor //粒子的颜色
16 cell.alphaSpeed = -0.4 //透明度改变速率
17 cell.velocity = 50//粒子运动速度
18 cell.velocityRange = 100//粒子速度范围,约束速度
19
20 emitterLayer.emitterCells = [cell]

CAEAGLLayer

  它是一个提供用OpenGL ES来绘图的layer,它可以预先假设要绘制的类型,快速绘制,它可以配合GLKit中的CLKView使用,具体demo专门写.

AVFoundation

  它是foundation框架里的,但是和layer的使用是一致的,demo如下

 1 var urlStr = NSBundle.mainBundle().pathForResource("1.mp4", ofType: nil)
 2 var url = NSURL(fileURLWithPath: urlStr!)
 3 var player = AVPlayer(URL: url)
 4
 5 var playLayer = AVPlayerLayer(player: player)
 6 playLayer.frame = CGRectMake(0, 0,400, 300)
 7 playLayer.backgroundColor = UIColor.grayColor().CGColor
 8 self.view.layer.addSublayer(playLayer)
 9
10 player.play()
时间: 2024-08-19 07:08:54

iOS核心动画高级技巧之图层变换和专用图层(二)的相关文章

iOS核心动画高级技巧之核心动画(三)

iOS核心动画高级技巧之CALayer(一) iOS核心动画高级技巧之图层变换和专用图层(二)iOS核心动画高级技巧之核心动画(三)iOS核心动画高级技巧之性能(四)iOS核心动画高级技巧之动画总结(五) 隐式动画 隐式动画主要作用于CALayer的可动画属性上面,UIView对应的layer是不可以的,只要你改变属性的值,它不是突兀的直接改变过去,而是一个有一个动画的过程,这个时间等属性你可以通过事务(CATransaction)来控制,如果你不自己提供一个事务,它的默认时间是0.25秒,当然

iOS核心动画高级技巧 - 8

iOS核心动画高级技巧 - 1 iOS核心动画高级技巧 - 2 iOS核心动画高级技巧 - 3 iOS核心动画高级技巧 - 4 iOS核心动画高级技巧 - 5 iOS核心动画高级技巧 - 6 iOS核心动画高级技巧 - 7 15. 图层性能 图层性能 要更快性能,也要做对正确的事情. ——Stephen R. Covey 在第14章『图像IO』讨论如何高效地载入和显示图像,通过视图来避免可能引起动画帧率下降的性能问题.在最后一章,我们将着重图层树本身,以发掘最好的性能. 15.1 隐式绘制 隐式

iOS核心动画高级技巧之CALayer(一)

UIView和CALayer的关系 在iOS中一个UIView对应着一个CALayer,视图的职责就是创建并管理这个图层,以确保当子视图在层级关系中添加或者被移除的时候,他们关联的图层也同样对应在层级关系树当中有相同的操作.实际上这些背后关联的图层才是真正用来在屏幕上显示和做动画,UIView仅仅是对它的一个封装,提供了一些iOS类似于处理触摸的具体功能,以及Core Animation底层方法的高级接口.(CALayer并不能响应事件,它提供了几个能判断一个触点时候再图层的范围之内) CALa

IOS核心动画高级技巧

今天发现个很不错学习IOS动画的网站,mark下  顺便推荐给大家 go http://zsisme.gitbooks.io/ios-/content/ 版权声明:本文为博主原创文章,未经博主允许不得转载.

《iOS核心动画高级技巧》part1-CALayer

UIView和CALayer的选择 可以发现,前面的2个效果不仅可以通过添加层来实现,还可以通过添加UIView来实现.如显示图片的层可以用一个UIImageView来实现. 既然CALayer和UIView都能实现相同的显示效果,那究竟该选择谁好呢? 其实,对比CALayer,UIView多了一个事件处理的功能.也就是说,CALayer不能处理用户的触摸事件,而UIView可以. 所以,在选择的过程中,需要考虑到实际的情况,如果显示出来的东西需要跟用户进行交互的话,用UIView:如果不需要跟

iOS核心动画学习整理

最近利用业余时间终于把iOS核心动画高级技巧(https://zsisme.gitbooks.io/ios-/content/chapter1/the-layer-tree.html)看完,对应其中一些知识做了相应的整理,整理为demo(https://github.com/PurpleSweetPotatoes/Layer_learn).此demo中都是基于教程书籍中的编程示例,并加上了注解以方便各位iOS爱好者学习使用. 在这里利用此教程中的基础知识做了2个小demo,活动指示器效果和火焰效

iOS核心动画Core Animation(一)

核心动画Core Animation(一) 一.简述 Core Animation是直接作用在CALayer上的(并非UIView上)非常强大的跨Mac OS X和iOS平台的动画处理API,Core Animation的动画执行过程都是在后台操作的,不会阻塞主线程. 二.核心动画常识 列举处核心动画的一些常识知识. 核心动画的本质:在后台移动图层中的内容,  执行完毕后图层本身的位置并没有发生变化. 如果是Xcode6之前的版本,要导入<QuartzCore/QuartzCore.h>框架,

iOS核心动画

iOS开发系列--让你的应用“动”起来 --iOS核心动画 概览 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥iOS动画全貌.在这里你可以看到iOS中如何使用图层精简非交互式绘图,如何通过核心动画创建基础动画.关键帧动画.动画组.转场动画,如何通过UIView的装饰方法对这些动画操作进行简化等.在今天的文章里您可以看到动画操作在iOS中是如何简单和高效,很多原来想做但是苦于没有思路的动画在iOS中将变得越发简单: CALayer CALayer简介 CAL

iOS核心动画中的常用类型

CATransaction 当我们在自定义的图层上修改某些支持动画的属性时,系统会为该属性的修改自动产生动画.这种其实属于隐式动画.隐式动画要得益于CATransaction. 一个CATransaction从调用CATransaction.begin()开始,以CATransaction.commit()结束.在这其间对图层属性的修改,会受该Transaction的控制,可以通过setAnimationDuration修改Transaction的duration. 系统的隐式动画是因为在Run