1.前言
转载请注明出处
http://blog.youkuaiyun.com/wangguoyang429883793/article/details/50428849
以平移为例子,总结了一下动画的实现方式。
2.实战
准备工作:
我们添加了一个红色的uiview圆和一个蓝色的calyaer圆,给屏幕添加了点击事件。
enum AniType: Int {
case ViewCenterNone
case ViewCenterAni
case Block
case Spring
case LayerNone
case CABasic
case Display
case Snap
}
var currentType:AniType? //当前动画的类型,因为我们要用多种方式实现
var circleView:UIView? //UIView 红色的圆 用于动画
var layer:CALayer? // CALayer 蓝色的圆 用于动画
var dynamicAnimator:UIDynamicAnimator?
override func viewDidLoad() {
super.viewDidLoad()
currentType = .Snap
dynamicAnimator = UIDynamicAnimator()
addView()
addLayer()
addOptionsBtn()
addTapGesture()
}
//添加 UIView 的圆
func addView(){
circleView = UIView(frame: CGRectMake(0,0,50,50))
self.view.addSubview(circleView!)
circleView!.backgroundColor = UIColor.redColor()
circleView?.layer.cornerRadius = 25
circleView?.center = CGPoint(x: 30,y: 60)
}
//添加 Layer 的圆
func addLayer(){
layer = CALayer()
layer?.bounds = CGRectMake(0, 0, 50, 50)
layer?.cornerRadius = 25
layer?.position = CGPoint(x: 30,y: 30)
layer?.backgroundColor = UIColor.blueColor().CGColor
self.view.layer.addSublayer(layer!)
}
//给主屏添加点击事件
func addTapGesture(){
let tap = UITapGestureRecognizer(target: self, action: "onTap:")
tap.numberOfTapsRequired = 1
tap.numberOfTouchesRequired = 1
self.view.addGestureRecognizer(tap)
}
//根据动画类型匹配动画
func onTap(tap:UITapGestureRecognizer){
let local = tap.locationInView(self.view)
switch(currentType!){
case .ViewCenterNone:
translationTypeViewCenterNone(local)
case .ViewCenterAni:
translationTypeViewCenterAni(local)
case .Block:
translationTypeBlock(local)
case .Spring:
translationTypeSpring(local)
case .LayerNone:
layerTypeNone(local)
case .CABasic:
layerTypeCABasic(local)
case .Display:
TypeDispaly(local)
case .Snap:
dynamicSnap(local)
default:break
}
}
func addOptionsBtn(){
let btn = UIButton(frame: CGRectMake(0,0,100,60))
btn.setTitle("动画方式", forState: .Normal)
btn.setTitleColor(UIColor.redColor(), forState: .Normal)
btn.addTarget(self, action: "onClick", forControlEvents: .TouchUpInside)
self.view.addSubview(btn)
btn.center = CGPoint(x: UIScreen.mainScreen().bounds.width - 60 , y: UIScreen.mainScreen().bounds.width - 60)
}
func onClick(){
showOptions()
}
//其他效果选项
func showOptions(){
let actionSheet = UIActionSheet()
actionSheet.addButtonWithTitle("UIView无动画")
actionSheet.addButtonWithTitle("UIview有动画")
actionSheet.addButtonWithTitle("UIview.animate")
actionSheet.addButtonWithTitle("弹簧动画")
actionSheet.addButtonWithTitle("Layer实现")
actionSheet.addButtonWithTitle("CABasic")
actionSheet.addButtonWithTitle("逐帧动画")
actionSheet.addButtonWithTitle("UIDynamicAnimator")
actionSheet.delegate = self
actionSheet.showInView(self.view)
}
func actionSheet(actionSheet: UIActionSheet, clickedButtonAtIndex buttonIndex: Int) {
switch(buttonIndex){
case 0:
currentType = .ViewCenterNone
case 1:
currentType = .ViewCenterAni
case 2:
currentType = .Block
case 3:
currentType = .Spring
case 4:
currentType = .LayerNone
case 5:
currentType = .CABasic
case 6:
currentType = .Display
case 7:
currentType = .Snap
default:
break
}
}
1.直接改变UIView.center:
定义了一个ViewCenterNone类型,只改变UIview的center,可以看到红色uiview移动但是没有动画效果。
func translationTypeViewCenterNone(local:CGPoint){
self.circleView?.center = local
}
2.直接改变UIView.center 加动画效果:
定义了一个ViewCenterNone类型,只改变UIview的center,可以看到红色uiview移动但是没有动画效果。
//移动UIview 有动画效果
func translationTypeViewCenterAni(local:CGPoint){
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(1.0)
self.circleView?.center = local
UIView.commitAnimations()
}
2.animateWithDuration:
UIView的动画封装
//UIView.animate 封装的动画
func translationTypeBlock(local:CGPoint){
UIView.animateWithDuration(1.0, animations: { () -> Void in
self.circleView?.center = local
}) { (finished) -> Void in
print("finished")
}
}
4.animateWithDuration 弹簧效果:
UIView的动画封装 加两个参数
①usingSpringWithDamping 阻尼系数 越小弹性越大
②initialSpringVelocity 初始速度 值越大速度越大
//UIView Spring 弹簧动画
//usingSpringWithDamping 阻尼系数 越小弹性越大
//initialSpringVelocity 初始速度
func translationTypeSpring(local:CGPoint){
UIView.animateWithDuration(5 , delay: 0, usingSpringWithDamping: 0.43, initialSpringVelocity: 5, options: .CurveEaseOut ,animations: { () -> Void in
self.circleView?.center = local
}) { (finished) -> Void in
print("end")
}
}
5.直接改变layer的position:
通过改变layer的position可以改变位置,但是对于CALayer和UIVIew是有区别的。
①CAlyaer当改变position时,会有一个平滑过渡的动画效果。因为它的属性是隐式动画的。也就是说会默认开启动画效果。
②UIview的layer改变position时却没有动画效果。这是因为UIview的根Layer是不会产生动画效果的。
//通过layer改变位置
func layerTypeNone(local:CGPoint){
self.layer?.position = local // 蓝色的圆是有动画效果的
self.circleView?.layer.position = local //红色的圆是没有动画效果的
}
6.CABasicAnimation 改变layer的属性:
//CABasicAnimation 改变layer的属性
func layerTypeCABasic(local:CGPoint){
let basicAni = CABasicAnimation(keyPath: "position") // 用position属性 来表示是位移动画
basicAni.toValue = NSValue(CGPoint: local)
basicAni.duration = 1.0//动画时间5秒
layer?.addAnimation(basicAni, forKey: "")
}
7.CADisplayLink :
CADisplayLink是ios中的逐帧动画 刷新频率是60次/秒,和系统的屏幕刷新频率相同,所以看上去会比较流畅。当屏幕刷新的时候会调用selector中的方法。
//创建CADisplayLink
var displaylink:CADisplayLink?
func TypeDispaly(local:CGPoint){
displaylink = CADisplayLink(target: self, selector: "onDisplayLink")
displaylink!.addToRunLoop(NSRunLoop.mainRunLoop(), forMode: NSDefaultRunLoopMode)
}
//向下移动
func onDisplayLink(){
circleView?.layer.position.y++
if circleView?.layer.position.y == self.view.frame.height - 30{
displaylink?.paused = true
}
}
8.UIDynamicAnimator :
UIDynamicAnimator物理学相关的动画方式。看起来会比较自然。
//吸附动画
func dynamicSnap(local:CGPoint){
let snapBehavior = UISnapBehavior(item: circleView!, snapToPoint: local)//吸附动画 参数①要产生动画的view②被吸附到点
snapBehavior.damping = 0.9
dynamicAnimator?.removeAllBehaviors()
dynamicAnimator?.addBehavior(snapBehavior)//dynamicAnimator物理学动画的执行者
}
3.总结
只是简单地总结了一下,并不全,还有一些实现方式没有写出。每一种的讲解并不深入,有机会会在写。
demo:https://github.com/wgy429883793/swift-ios-translationAniDemo
欢迎批评,吐槽,点赞,留言。