IOS动画使用总结
IOS中动画主要有
视图动画UIViewAnimation
和核心动画Core Animation
完成。本文将详细介绍这两种动画的使用方法。
思维导图
UIViewAnimation
这是一种相对简单的动画制作方法,通过调用UIView.animateWithDuration
这种方法可以实现各种各样的动画。
UIView
UIView中有一些允许被改变的参数,
在以下动画的闭包函数里面就可以改变UIView的上述参数。
UIView.animateWithDuration 构造函数
/**
* Give a Double type as duration time.
* And give the clossure function to implement relate animation.
*/
UIView.animateWithDuration(NSTimeInterval) {
// code
}
UIView.animateWithDuration(duration, animations: {
// aniamtion function
}) { (Bool_para) in
// after finish animation
// this function will be called.
}
/**
* delay means when animation will be called.
* options means which kinds of animations will be used.
* and pay attention to options.
* it pass the value as array!
*/
UIView.animateWithDuration(NSTimeInterval, delay: NSTimeInterval, options: UIViewAnimationOptions, animations: {
// code
}) { (Bool) in
// code
}
UIViewAnimationOptions
转场效果:
- TransitionNone //
无转场动画 - TransitionFlipFromLeft //
转场从左翻转 - TransitionFlipFromRight //
转场从右翻转 - TransitionCurlUp //
上卷转场 - TransitionCurlDown //
下卷转场 - TransitionCrossDissolve //
转场交叉消失 - TransitionFlipFromTop //
转场从上翻转 - TransitionFlipFromBottom //
转场从下翻转
与时间曲线有关的:
- CurveLinear // 线性相关
- CurveEaseOut // 慢出
- CurveEaseInOut // 慢进慢出
- CurveEaseIn // 慢进
动画控制:
- OverrideInheritedOptions // 对于嵌套动画,忽略夫视图的options参数
- OverrideInheritedCurve // 忽略夫视图的时间曲线参数
- OverrideInheritedDuration // 忽略夫视图的持续时间参数
- AllowAnimatedContent // 允许内容动画
- Repeat // 持续重复
- Autoreverse // 自动回到原来的状态
- AllowUserInteraction // 允许用户交互
- ……
视图转场
要做出像ibooks里面页翻动的效果可以使用转场动画。
转场的函数提供了两种重载方法。
对于第二种方法: toView added to fromView.superview, fromView removed from its superview.
@IBOutlet weak var mSecondView: UIView!
@IBOutlet weak var mThirdView: UIView!
func repeatView() {
UIView.transitionFromView(self.mSecondView, toView: mThirdView, duration: 2, options: [.AllowAnimatedContent, .TransitionCurlUp]) { (fine) in
print("fine")
}
}
具体例子
动画允许嵌套进行,但需要注意的是,如果嵌套了动画,该动画的参数默认继承于他的夫动画,如果需要改变相关参数,需要显式给出三个参数。(Override开头的option)
@IBOutlet weak var mSecondView: UIView!
@IBOutlet weak var mFirstView: UIView!
@IBOutlet weak var mFirstViewSubview: UIView!
@IBOutlet weak var mThirdView: UIView!
func optionAnimation() {
UIView.animateWithDuration(1, delay: 0, options:UIViewAnimationOptions.CurveEaseIn, animations: {
self.mSecondView.frame.origin.x += 100
UIView.animateWithDuration(1, delay: 0, options: [UIViewAnimationOptions.OverrideInheritedCurve, UIViewAnimationOptions.CurveLinear], animations: {
self.mSecondView.frame.origin.x += 100
}, completion: { (Finesh) in
print("Finish 2")
})
}) { (Finish) in
print("Finish 1")
}
UIView.transitionWithView(self.mFirstView, duration: 2.0, options: [UIViewAnimationOptions.AllowAnimatedContent, UIViewAnimationOptions.TransitionCurlUp], animations: {
self.mFirstViewSubview.frame.origin.x += 50
}, completion: { (Finish) in
print("Yes")
})
}
Core Animation
核心动画是一种更加高级的动画制作方法,但相对会麻烦些。
继承关系图:
CALayer
动画的所用具体操作都是在layer上进行的。形象地说,layer就是一个actor。
每个Layer都有以下的属性:
- backgroundColor
- shadowOpacity
- cornerRadius
- shadowOffset
- shadowColor
- border
- …..
var layer : CALayer!
override func viewDidLoad() {
super.viewDidLoad()
layer = CALayer()
layer.frame = CGRectMake(50, 50, 50, 50)
layer.backgroundColor = UIColor.magentaColor().CGColor
layer.shadowColor = UIColor.blackColor().CGColor
layer.shadowOffset = CGSizeMake(10, 10)
layer.cornerRadius = 10
layer.shadowOpacity = 1
self.view.layer.addSublayer(layer)
}
CAAnimation
CAAnimation是动画的具体内容,形象的说,就是演员的剧本。
隐式动画
通过改变layer.position可以改变它的位置,但这个改变是带有动画效果的。
// Impliacte animation:
func implicateAnimation() {
layer.position.x += 100
layer.position.y += 100
}
显式动画(CABasicAnimation)
通过调用CABasicAnimation
, 它需要传入一个keyPath:
- transform.scale
- transform.scale.x
- transform.scale.y
- transform.rotation.z
- opacity
- margin
- zPosition
- backgroundColor
- cornerRadius
- borderWidth
- bounds
- contents
- contentsRect
- cornerRadius
- frame
- hidden
- mask
- masksToBounds
- opacity
- position
- shadowColor
- shadowOffset
- shadowOpacity
- shadowRadius
具体例子:
func BasicAnimation() {
let image = UIImageView(image: UIImage(named: "100006"))
image.frame = CGRectMake(160, 300, 68, 68)
self.view.addSubview(image)
// First of all, set actor.
let mlayer = image.layer
// Secondly, write the first drama
/// The keyPath is the name of animation.
let scaleAnimation = CABasicAnimation(keyPath: "transform.scale")
scaleAnimation.fromValue = 1.0
scaleAnimation.toValue = 1.5
scaleAnimation.duration = 1.5
scaleAnimation.repeatCount = MAXFLOAT
scaleAnimation.autoreverses = true
// And, write another drama to set opequa.
let opequaAnimation = CABasicAnimation(keyPath: "opacity")
opequaAnimation.fromValue = 0.0
opequaAnimation.toValue = 1.0
opequaAnimation.duration = 1.5
opequaAnimation.repeatCount = MAXFLOAT
opequaAnimation.autoreverses = true
// Lastly, notificate the mlayer to do as the drama.
mlayer.addAnimation(scaleAnimation, forKey: "scaleAnimation")
mlayer.addAnimation(opequaAnimation, forKey: "opequaAnimation")
}
关键帧动画
func keyFrameAnimation() {
let image = UIImageView(image: UIImage(named: "100001"))
image.frame = CGRectMake(160, 300, 68, 68)
self.view.addSubview(image)
let mlayer = image.layer
let keyAnimate = CAKeyframeAnimation(keyPath: "position")
/// change the position of the layer.
let value0 = NSValue(CGPoint : CGPointMake(mlayer.position.x, mlayer.position.y))
let value1 = NSValue(CGPoint: CGPointMake(mlayer.position.x, mlayer.position.y + 50))
let value2 = NSValue(CGPoint: CGPointMake(mlayer.position.x + 50, mlayer.position.y + 50))
let value3 = NSValue(CGPoint: CGPointMake(mlayer.position.x + 50, mlayer.position.y))
let value4 = NSValue(CGPoint : CGPointMake(mlayer.position.x, mlayer.position.y))
keyAnimate.values = [value0, value1, value2, value3, value4]
/// the function of how to change the layer position.
let ft0 = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
let ft1 = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
let ft2 = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
let ft3 = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)
keyAnimate.timingFunctions = [ft0, ft1, ft2, ft3]
// change the timing usage of which function
keyAnimate.keyTimes = [0.0, 0.2, 0.5, 0.7, 1]
keyAnimate.duration = 3.0
keyAnimate.autoreverses = false
keyAnimate.repeatCount = MAXFLOAT
mlayer.addAnimation(keyAnimate, forKey: "keyAnimate")
}