iOS核心动画高级技巧之图层变换和专用图层(二)
2015-07-13 21:39
585 查看
iOS核心动画高级技巧之CALayer(一)
iOS核心动画高级技巧之图层变换和专用图层(二)
iOS核心动画高级技巧之核心动画(三)
iOS核心动画高级技巧之性能(四)
iOS核心动画高级技巧之动画总结(五)
仿射变换
iOS仿射变换是CGAffineTransform,仿射变换的特点是变换后的图形对边依然是平行的,它包括 CGAffineTransformMakeRotation(CGFloat angle) / CGAffineTransformMakeScale(CGFloat sx, CGFloat sy) / CGAffineTransformMakeTranslation(CGFloat tx, CGFloat ty),直接看代码
这里只需要注意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轴的旋转都不会使它的方向改变,这是由于矩阵的值表示的范围广,不会互相影响.
由于3D变换分成多个方向的,所以沿X或Y方向的旋转就像缩放了一样,可以通过设置向量对应的值来修复这个效果,让它看上去更真实一点,结果它会有一个倾斜角度,有一个投影效果,这样当你做平移的时候会改变显示的大小,所以一般不要一起用了,而要让这个效果有效,需要在初始化transform时就设置m34的值(这个值最好在-1/500.0 到 -1/5000.0之间),放到后面没有效果,在后面也不能用scale放大缩小,不然会覆盖这个值.所以这个效果基本是单独拿出来显示效果的.
当你在投射的方向平移足够大的距离,它最后的成像就是一个点了,这个点一般是图层的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,它对比画图有很大的优势,它使用了硬件加速,所以绘图速度很快,它不需要寄宿图片所以不会使用太多内存,它也不会和普通图层一样被裁剪掉,而且它不会被像素化,最后就不会模糊.你可以设置
View Code
CAScrollLayer
CAScrollLayer和UIScrollView类似,它和CALayer相比多了个scrollPoint的方法,如果要用这个方法可以使用CAScrollLayer
CATiledLayer
CATiledLayer的可以做到图片/PDF等的分割显示,如果一个一张图片分辨率超过2048*2048(因平台不同),超过了OpenGL最大纹理尺寸,所以会有性能问题,一个PDF一般也比较大,所以容易出现性能问题(后面会单独写一个demo)
CAEmitterLayer
CAEmitterLayer能模仿粒子反射,如果火焰等,能控制粒子颜色/放射的速率,透明度,方向,个数等.
CAEAGLLayer
它是一个提供用OpenGL ES来绘图的layer,它可以预先假设要绘制的类型,快速绘制,它可以配合GLKit中的CLKView使用,具体demo专门写.
AVFoundation
它是foundation框架里的,但是和layer的使用是一致的,demo如下
iOS核心动画高级技巧之图层变换和专用图层(二)
iOS核心动画高级技巧之核心动画(三)
iOS核心动画高级技巧之性能(四)
iOS核心动画高级技巧之动画总结(五)
仿射变换
iOS仿射变换是CGAffineTransform,仿射变换的特点是变换后的图形对边依然是平行的,它包括 CGAffineTransformMakeRotation(CGFloat angle) / CGAffineTransformMakeScale(CGFloat sx, CGFloat sy) / CGAffineTransformMakeTranslation(CGFloat tx, CGFloat ty),直接看代码
blueView = UIView() blueView.frame = CGRectMake(50, 100, 100, 100) blueView.backgroundColor = UIColor.blueColor() self.view.addSubview(blueView) yellowView = UIView() yellowView.frame = CGRectMake(50 + 200 / 1.414, 100, 100, 100)//注意yellowView的水平位置,和blueView作对比 yellowView.backgroundColor = UIColor.yellowColor() self.view.addSubview(yellowView) blueView.transform = CGAffineTransformIdentity //初始化transform blueView.transform = CGAffineTransformMakeScale(0.5, 0.5 ) //缩小0.5倍 blueView.transform = CGAffineTransformRotate(blueView.transform, CGFloat(M_PI_4)) //旋转pi/4 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轴的旋转都不会使它的方向改变,这是由于矩阵的值表示的范围广,不会互相影响.
blueLayer.transform = CATransform3DIdentity //初始化transform blueLayer.transform = CATransform3DMakeScale(0.5, 0.5, 0) //缩小0.5倍 blueLayer.transform = CATransform3DRotate(blueLayer.transform,CGFloat( M_PI_4 ), 0.0, 1.0, 0) //旋转pi/4 blueLayer.transform = CATransform3DTranslate(blueLayer.transform,400, 0, 0) //平移400
由于3D变换分成多个方向的,所以沿X或Y方向的旋转就像缩放了一样,可以通过设置向量对应的值来修复这个效果,让它看上去更真实一点,结果它会有一个倾斜角度,有一个投影效果,这样当你做平移的时候会改变显示的大小,所以一般不要一起用了,而要让这个效果有效,需要在初始化transform时就设置m34的值(这个值最好在-1/500.0 到 -1/5000.0之间),放到后面没有效果,在后面也不能用scale放大缩小,不然会覆盖这个值.所以这个效果基本是单独拿出来显示效果的.
var transform = CATransform3DIdentity //初始化transform transform.m34 = -1 / 500.0 //设置m34的值 // transform = CATransform3DScale( transform, 0.5, 0.5, 0) //缩小0.5倍,这里不能用 transform = CATransform3DRotate(transform,CGFloat( M_PI_4 ), 0.0, 1.0, 0) //旋转pi/4 transform = CATransform3DTranslate(transform,400, 0, 0) //平移400 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() shapePath.moveToPoint(CGPointMake(175, 100)) shapePath.addArcWithCenter(CGPointMake(150, 100), radius: 25, startAngle: 0, endAngle:CGFloat( 2 * M_PI ), clockwise: true) shapePath.moveToPoint(CGPointMake(150, 125)) shapePath.addLineToPoint(CGPointMake(150, 175)) shapePath.addLineToPoint(CGPointMake(125, 225)) shapePath.moveToPoint(CGPointMake(150, 175)) shapePath.addLineToPoint(CGPointMake(175, 225)) shapePath.moveToPoint(CGPointMake(100, 150)) shapePath.addLineToPoint(CGPointMake(200, 150)) let shapeLayer = CAShapeLayer() shapeLayer.strokeColor = UIColor.redColor().CGColor shapeLayer.fillColor = UIColor.clearColor().CGColor shapeLayer.lineWidth = 5 shapeLayer.lineJoin = kCALineJoinRound shapeLayer.lineCap = kCALineCapRound shapeLayer.path = shapePath.CGPath self.view.layer.addSublayer(shapeLayer)
DEMO2: 1 var rect = CGRectMake(50, 50, 100, 100); var radii = CGSizeMake(20, 20); var corners = UIRectCorner.TopRight | UIRectCorner.BottomRight | UIRectCorner.BottomLeft var shapePath = UIBezierPath(roundedRect: rect, byRoundingCorners: corners, cornerRadii: radii)
reflectionLayer = CAReplicatorLayer() var img = UIImage(named: "3333.jpg") reflectionLayer.frame = CGRectMake((self.view.bounds.size.width - img!.size.width) / 2 , 100, img!.size.width, img!.size.height * 1.5) reflectionLayer.backgroundColor = UIColor.grayColor().CGColor self.view.layer.addSublayer(reflectionLayer) var transform = CATransform3DIdentity transform = CATransform3DScale(transform, 1, -0.5, 1); transform = CATransform3DTranslate(transform, 0, -img!.size.height * 3 / 4 + 2, 0.0); reflectionLayer.instanceTransform = transform; reflectionLayer.instanceCount = 2 var imageLayer = CALayer() imageLayer.frame = CGRect(x: 0, y: 0, width: img!.size.width, height: img!.size.height) imageLayer.backgroundColor = UIColor.whiteColor().CGColor imageLayer.contents = img!.CGImage //layer.anchorPoint = CGPointMake(0, 0) reflectionLayer.addSublayer(imageLayer) //设置透明度,在外面用个层来设置 var gradientLayer = CAGradientLayer() gradientLayer.colors = [UIColor.whiteColor().colorWithAlphaComponent(0.2).CGColor, UIColor.whiteColor().CGColor] 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) self.view.layer.addSublayer(gradientLayer) //设置文字 var textLayer = CATextLayer() textLayer.frame = CGRectMake(80, 50, 200, 300) self.view.layer.addSublayer(textLayer) //设置它的属性 textLayer.foregroundColor = UIColor.redColor().CGColor textLayer.alignmentMode = kCAAlignmentJustified textLayer.wrapped = true //它的font是CGFont类型,需要大小字体分开设置 var font = UIFont.systemFontOfSize(24) textLayer.font = CGFontCreateWithFontName(font.fontName) textLayer.fontSize = font.pointSize var textStr = "What a fuck!" textLayer.string = textStr //它contentScale默认是1,为了让它以retina的质量来显示,设置为2 textLayer.contentsScale = UIScreen.mainScreen().scale imageLayer.addSublayer(textLayer) var basicAnimation = CABasicAnimation(keyPath: "position.y") basicAnimation.duration = 2.0 basicAnimation.fromValue = Float( textLayer.position.y ) var toValue:Float = Float( textLayer.position.y + 100.0) basicAnimation.toValue = NSNumber(float: toValue) basicAnimation.removedOnCompletion = true basicAnimation.fillMode = kCAFillModeForwards textLayer.addAnimation(basicAnimation, forKey: nil) // textLayer.frame.origin.y = CGFloat( toValue) textLayer.position = CGPointMake(textLayer.position.x, textLayer.position.y + 100.0)
View Code
CAScrollLayer
CAScrollLayer和UIScrollView类似,它和CALayer相比多了个scrollPoint的方法,如果要用这个方法可以使用CAScrollLayer
NSTimer.scheduledTimerWithTimeInterval(2, target: self, selector: NSSelectorFromString("setPosition"), userInfo: nil, repeats: false) func setPosition () { self.scrollLayer.scrollToPoint(CGPointMake(0, 100)) }
CATiledLayer
CATiledLayer的可以做到图片/PDF等的分割显示,如果一个一张图片分辨率超过2048*2048(因平台不同),超过了OpenGL最大纹理尺寸,所以会有性能问题,一个PDF一般也比较大,所以容易出现性能问题(后面会单独写一个demo)
CAEmitterLayer
CAEmitterLayer能模仿粒子反射,如果火焰等,能控制粒子颜色/放射的速率,透明度,方向,个数等.
emitterLayer = CAEmitterLayer() emitterLayer.frame = CGRectMake(100 , 100, 200, 200) emitterLayer.backgroundColor = UIColor.grayColor().CGColor self.view.layer.addSublayer(emitterLayer) emitterLayer.renderMode = kCAEmitterLayerAdditive emitterLayer.emitterPosition = CGPointMake(emitterLayer.frame.size.width / 2, emitterLayer.frame.size.height / 2) var cell = CAEmitterCell() cell.contents = UIImage(named: "lizi.png")?.CGImage cell.birthRate = 10 //粒子出现的速率 cell.lifetime = 4.0 //声明周期,秒 cell.emissionRange = 2 //发射的方向 cell.color = UIColor(red: 1, green: 1, blue: 0.5, alpha: 1).CGColor //粒子的颜色 cell.alphaSpeed = -0.4 //透明度改变速率 cell.velocity = 50//粒子运动速度 cell.velocityRange = 100//粒子速度范围,约束速度 emitterLayer.emitterCells = [cell]
CAEAGLLayer
它是一个提供用OpenGL ES来绘图的layer,它可以预先假设要绘制的类型,快速绘制,它可以配合GLKit中的CLKView使用,具体demo专门写.
AVFoundation
它是foundation框架里的,但是和layer的使用是一致的,demo如下
var urlStr = NSBundle.mainBundle().pathForResource("1.mp4", ofType: nil) var url = NSURL(fileURLWithPath: urlStr!) var player = AVPlayer(URL: url) var playLayer = AVPlayerLayer(player: player) playLayer.frame = CGRectMake(0, 0,400, 300) playLayer.backgroundColor = UIColor.grayColor().CGColor self.view.layer.addSublayer(playLayer) player.play()
相关文章推荐
- iOS系统中使用OpenCV(备注有空研究一下)
- IOS开发-06.提示框
- iOS实现抽屉效果
- 使用蒲公英来发布iOS内侧版本
- iOS开发常用的第三方类库
- IOS编程的一些基本概念
- iOS 本地加载js文件
- IOS开发中,SVN如何恢复到某一个版本(以Cornerstone为例)
- 解决iOS下input和fixed 问题
- iOS 各种调试技巧豪华套餐
- 关于iOS逆向工程的工具(一)
- IOS
- IOS沙盒
- 19-XMPP
- ios 启动页问题
- ios 推送通知
- 网易新闻iOS版在开发过程中曾经使用过的第三方开源类库、组件
- L1 AudioService.adjustSuggestedStreamVolume
- Xcode6解决storyboard没有箭头的问题
- IOS 请求服务器的方式