首先介绍一下CALayer的一些属性。
bounds: 图层大小
position: 图层中心点的位置,类似与UIView的center;用来设置CALayer在父层中的位置;以父层的左上角为原点(0,0)
transform: 用于图层的移动、缩放、旋转等
borderColor: 图层边框颜色
borderWidth: 图层边框宽度
cornerRadius: 图层圆角半径
shadowOffset: 阴影偏移量
shadowOpacity: 阴影透明度,注意默认为0,如果设置阴影必须设置此属性
shadowPath: 阴影形状
shadowRadius: 阴影模糊半径
contents: 图层显示内容,例如可以将图片作为图层内容显示
mask: 图层蒙版
masksToBounds: 子图层是否剪切图层边界,默认是false
opacity: 图层透明度,类似与UIView的alpha
anchorPoint: 称『定位点』、『锚点』,该描述是相对于x、y位置比例而言的默认在图像中心点(0.5、0.5)的位置;决定着CALayer身上的哪个点会再position属性所指的位置,以自己的左上角为原点(0,0);它的x、y取值范围都是0~1。
contentsRect: 图层显示内容的大小和位置
doubleSided: 图层背景是否显示,默认是YES
frame: 图层大小和位置,不支持隐式动画,所以CALyaer中很少使用frame,通常使用bounds和position代替
CABasicAnimation
let flyRight = CABasicAnimation(keyPath: "position.x")
flyRight.fromValue = -view.bounds.size.width/2
flyRight.toValue = view.bounds.size.width/2
flyRight.duration = 0.5
heading.layer.add(flyRight, forKey: nil)
fromValue:为keyPath设置初始属性值
toValue:为keyPath设置结束属性值
duration:动画持续时间
add(_:forKey:):拷贝一份flyRight的动画对象,将flyRight的副本加入heading.layer执行,key用来区分heading.layer中不同的animation。
在add(_:forKey:)前面添加如下方法
flyRight.beginTime = CACurrentMediaTime() + 0.3
beginTime表示动画开始的绝对时间,使用*CACurrentMediaTime()*获取当前时间,加上你希望延迟执行的时间
fillMode属性
flyRight.fillMode = kCAFillModeBackwards
kCAFillModeBackwards:动画开始前就显示动画的第一帧,而不是显示layer的真实位置
flyRight.fillMode = kCAFillModeForwards
kCAFillModeForwards:动画结束后持续显示最后一帧,直到你移除当前动画。(通常在设置forwards属性后,你需要做一些其他的改变才能让最后一帧一直显示,后面会讲到)
flyRight.fillMode = kCAFillModeBoth
kCAFillModeBoth是Backwards和Forwards的结合。
动画和真实控件位置
假设我们创建了一个textField,将其layer位置设置在屏幕外textfield.layer.position.x -= view.bounds.width,那么它的动画初始位置也是:
flyRight.fromValue = -view.bounds.size.width/2
我们创建一个移入屏幕的动画
flyRight.toValue = view.bounds.size.width/2
当动画完成后,textField并不会停留在屏幕中央,而是会回到它的真实位置(即初始位置),如果我们想让它在屏幕中央保留,可以将isRemovedOnCompletion设置为false
isRemovedOnCompletion属性
这个属性值表明动画完成后是否移除当前动画,默认值是true表示完成后移除,设置为false并结合fillMode可以让动画完成后不移除并一直显示最后一帧 ,但是此时你会发现,你无法对上述的textField进行任何输入操作,因为控件的真实位置并不在屏幕中央,为了达到预期效果,最好避免任何时候更改此属性的值,而是在动画完成后重新设置真实控件的位置。
结构体的使用
在设置动画属性值时,也可以使用结构体的方式,利用NSValue进行“包裹”。
let move = CABasicAnimation(keyPath: "position")
move.duration = 1.0
move.fromValue = NSValue(cgPoint: CGPoint(x: 100.0, y: 100.0))
move.toValue = NSValue(cgPoint: CGPoint(x: 200.0, y: 200.0))”
除了CGPoint,还有其他结构体,例如CGSize、CGRect、CATransform3D等都可以进行这种操作。
图形变化
与动画相关的图形形状的变化。
CAShapeLayer继承至CALayer,那么哪些属性可以用于制作动画呢?
path:修改layer的形状
fillColor:更改填充色
lineDashPhase:在你的形状周围创建选框等效果
lineWidth:更改边框宽度
利用CAShapeLayer初始化一个circleLayer,添加动画。例如
let morphAnimation = CABasicAnimation(keyPath: "path")
morphAnimation.duration = animationDuration
morphAnimation.toValue = UIBezierPath(ovalIn: morphedFrame).cgPath
morphAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
circleLayer.add(morphAnimation, forKey: nil)