swift ios 平移动画(8种方式)

本文详细介绍了在Swift中实现iOS平移动画的8种方法,包括直接改变UIView.center、使用animateWithDuration、CABasicAnimation以及UIDynamicAnimator等。通过实例展示了不同方法的效果,如弹簧效果和物理学动画,提供了相应的代码示例和链接到完整项目的GitHub仓库。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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: "")
    }

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
欢迎批评,吐槽,点赞,留言。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值