iOS动画和特效(一)UIView动画和CoreAnimation

一个简单的例子作为iOS动画系类的开始 QuickExampleViewController

UIView的方法中有几个易用的静态方法可以做出动画效果,分别是UIView.beginAnimations() -> UIView.commitAnimations() 和UIView.animateWithDuration()方法
我们以一个UIView,每点击一次向右移动100,变色,加速运动这个简单的动效作为例子。
转载请注明出处

使用UIView.beginAnimations() -> UIView.commitAnimations()实现


        //开始动画配置
        UIView.beginAnimations("view1Animation", context: nil)
        //运动时间
        UIView.setAnimationDuration(0.2)
        //设置运动开始和结束的委托 animationDidStart and animationDidStop
        UIView.setAnimationDelegate(self)
        /*
            缓动方式
            EaseInOut // slow at beginning and end
            EaseIn // slow at beginning
            EaseOut // slow at end
            Linear
        */
        UIView.setAnimationCurve(.EaseIn)
        //位置运动
        theView.frame = CGRect(x: theView.frame.origin.x+100, y: theView.frame.origin.y, width: theView.frame.size.width, height: theView.frame.height)
        //颜色渐变
        theView.backgroundColor = UIColor.greenColor()
        //透明度渐变
        theView.alpha = 0.5
        //动画开始
        UIView.commitAnimations()

使用更简单的和UIView.animateWithDuration()实现


    UIView.animateWithDuration(0.2, delay: 0.5, options: UIViewAnimationOptions.CurveEaseIn, animations: { () -> Void in
                //位置运动
                theView.frame = CGRect(x: theView.frame.origin.x+100, y: theView.frame.origin.y, width: theView.frame.size.width, height: theView.frame.height)
                //颜色渐变
                theView.backgroundColor = UIColor.greenColor()
                //透明度渐变
                theView.alpha = 0.5
            }) { (isCompletion) -> Void in
                NSLog("completion")
        }

animateWithDuration的方法有4个从载方法,参数不同,根据需要调用。其中最后一个代理一个阻尼系数和回弹系数,使用他可以做出更加逼真的运动效果

     //usingSpringWithDamping 阻尼,范围0-1,阻尼越接近于0,弹性效果越明显
     UIView.animateWithDuration(0.2, delay: 0, usingSpringWithDamping: 0.9, initialSpringVelocity: 1, options: UIViewAnimationOptions.CurveEaseIn, animations: { () -> Void in
         theView.frame = CGRect(x: theView.frame.origin.x+100, y: theView.frame.origin.y, width: theView.frame.size.width, height: theView.frame.height)
        }, completion: nil)

本节介绍的几个方法,已经可以做出许多的简单动画效果了,这说明apple对高级别对象的动画api封装做的很不错。代码见QuickExampleViewController.swift

Core Animation的类图



CAAnimation:核心动画的基础类,不能直接使用,负责动画运行时间、速度的控制,本身实现了CAMediaTiming协议。

CAPropertyAnimation:属性动画的基类(通过属性进行动画设置,注意是可动画属性),不能直接使用。

CAAnimationGroup:动画组,动画组是一种组合模式设计,可以通过动画组来进行所有动画行为的统一控制,组中所有动画效果可以并发执行。

CATransition:转场动画,主要通过滤镜进行动画效果设置。

CABasicAnimation:基础动画,通过属性修改进行动画参数控制,只有初始状态和结束状态。

CAKeyframeAnimation:关键帧动画,同样是通过属性进行动画参数控制,但是同基础动画不同的是它可以有多个状态控制。

基本动画 CABasicAnimation

还记得上一节简单的动画吗,一个uiview向左平移100,这节我们使用CABasicAnimation实现相同的效果


            let baseAnimation = CABasicAnimation(keyPath: "position")
            //baseAnimation.fromValue 初始位置,如果不设就是当前位置
//          let point = CGPoint(x: theView.layer.position.x+100, y: theView.layer.position.y)
//          baseA baseAnimation.toValue = NSValue(CGPoint:point)nimation.toValue = NSValue(CGPoint:point)//绝对位置
            baseAnimation.byValue = NSValue(CGPoint:CGPoint(x: 100, y: 0))//相对位置

            //动画其他属性
            baseAnimation.duration = 0.2
            baseAnimation.repeatCount = 1
            baseAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)//加速运动
            //baseAnimation.timingFunction = CAMediaTimingFunction(controlPoints: 0.5, 0, 0.9, 0.7)//自定义加速的曲线参数

            //这两个属性若不设置,动画执行后回复位
            baseAnimation.removedOnCompletion = false
            baseAnimation.fillMode = kCAFillModeForwards

            //可以在动画中缓存一些
            //baseAnimation.setValue(NSValue(CGPoint: point), forKey: "startPoint")
            //开始动画
            theView.layer.addAnimation(baseAnimation, forKey: "theViewMoveRight100")

CABasicAnimation注意点

使用上面的代码之后,发现点击之后view确实向右移动了100,但是再次点击红色区域却发现不会继续移动了,但是点击移动前view所在位置,红色区域会重复移动,如图

出现这种现象的原因是因为动画是通过view的layer设置位置的。而设置layer的位置后,uiview的位置是不会发生变化的,所以虽然看见红色移动了,但其实红色view.frame没变化,所以点击区域也没变化。那么如何解决?

解决的思路是在每次动画结束后,把view.frame的位置重新设置成移动后的位置。代码如下:

//步骤1,设置动画的委托
 baseAnimation.delegate = self

//步骤2:将移动后的点和要移动的view放入baseAnimation的context
baseAnimation.setValue(NSValue(CGPoint: endPoint), forKey: "endPoint")
baseAnimation.setValue(theView, forKey: "sender")

//步骤3:重写animationDidStop,layer.position
override func animationDidStop(anim:CAAnimation, finished flag: Bool) {
    let endPoint = anim.valueForKey("endPoint")?.CGPointValue
    let theView = anim.valueForKey("sender") as! UIView
    theView.layer.position = endPoint!
}

其他注意几个地方

1:keyPath用于区分BasicAnimation动画类型

  /*
        可选的KeyPath
        transform.scale = 比例转换
        transform.scale.x
        transform.scale.y
        transform.rotation = 旋转
        transform.rotation.x
        transform.rotation.y
        transform.rotation.z
        transform.translation
        transform.translation.x
        transform.translation.y
        transform.translation.z

        opacity = 透明度
        margin
        zPosition
        backgroundColor 背景颜色
        cornerRadius 圆角
        borderWidth
        bounds
        contents
        contentsRect
        cornerRadius
        frame
        hidden
        mask
        masksToBounds
        opacity
        position
        shadowColor
        shadowOffset
        shadowOpacity
        shadowRadius

    */

2:动画执行后不恢复原位

//这两个属性若不设置,动画执行后回复位
baseAnimation.removedOnCompletion = false
baseAnimation.fillMode = kCAFillModeForwards

CABasicAnimation 组合动画

组合动画就是把一组CABasicAnimation组合使用,我们以组合移动、旋转、缩放特效为例


    //组合动画
    func groupAnimation(theView:UIView){

        //向右平移100
        let mAnimation = CABasicAnimation(keyPath: "position")
        //baseAnimation.fromValue 初始位置,如果不设就是当前位置
        let endPoint = CGPoint(x: theView.layer.position.x+100, y: theView.layer.position.y)
        mAnimation.toValue = NSValue(CGPoint:endPoint)//绝对位置

        //baseAnimation.byValue = NSValue(CGPoint:CGPoint(x: 100, y: 0))//相对位置

        //x轴旋转动画
        let xAnimation = CABasicAnimation(keyPath: "transform.rotation.x")
        (xAnimation as CABasicAnimation).byValue =  NSNumber(double:M_PI*500)
        xAnimation.duration = 1.5

        //y轴旋转动画
        let yAnimation = CABasicAnimation(keyPath: "transform.rotation.y")
        (yAnimation as CABasicAnimation).byValue =  NSNumber(double:M_PI*200)

        //缩放动画
        let sAnimation = CABasicAnimation(keyPath: "transform.scale")
        // 动画选项设定
        sAnimation.autoreverses = true // 动画结束时执行逆动画
        // 缩放倍数
        sAnimation.fromValue = NSNumber(double:0.1) // 开始时的倍率
        sAnimation.toValue = NSNumber(double:1.5) // 结束时的倍率

        //动画组
        let groupAnimation = CAAnimationGroup()

        // 动画选项设定,动画组统一设置或者单独设置
        groupAnimation.duration = 3.0;
        groupAnimation.repeatCount = 1;
        groupAnimation.animations = [xAnimation,yAnimation,sAnimation,mAnimation]
        //这两个属性若不设置,动画执行后回复位
        groupAnimation.removedOnCompletion = false
        groupAnimation.fillMode = kCAFillModeForwards
        groupAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)//加速运动
        groupAnimation.delegate = self
        //可以在动画中缓存一些
        groupAnimation.setValue(NSValue(CGPoint: endPoint), forKey: "endPoint")
        groupAnimation.setValue(theView, forKey: "sender")
        //执行动画
        theView.layer.addAnimation(groupAnimation, forKey: "theViewMoveRotation90")
    }

关键帧动画 CAKeyframeAnimation

关键帧动画和基本动画也很相似,通过keyPath设置动画类型,才对齐进行一组关键值的设定。数据变化也有2种形式,一种是关键点,一种是路径,比如实例中的按一个贝塞尔弧移动view。


        //关键帧动画
        //keyPath和basicAnimation的类型相同,@see BasicAnimationViewController.swift
        let keyframeAnimation = CAKeyframeAnimation(keyPath: "position")

        //线段的位置移动
//        keyframeAnimation.values = [
//                                        NSValue(CGPoint: CGPoint(x: 10, y: 100)),
//                                        NSValue(CGPoint: CGPoint(x: 30, y: 100)),
//                                        NSValue(CGPoint: CGPoint(x: 30, y: 120)),
//                                        NSValue(CGPoint: CGPoint(x: 60, y: 120)),
//                                        NSValue(CGPoint: CGPoint(x: 60, y: 100)),
//                                        NSValue(CGPoint: CGPoint(x: 106, y: 210)),
//                                        NSValue(CGPoint: CGPoint(x: 106, y: 410)),
//                                        NSValue(CGPoint: CGPoint(x: 300, y: 310))
//                                   ]

        //弧线位置移动
        let path = CGPathCreateMutable()
        CGPathMoveToPoint(path, nil, 50, 50)
        CGPathAddCurveToPoint(path, nil, 50, 50, 700, 300, 30, 500)
        keyframeAnimation.path = path

        //设置其他属性
        keyframeAnimation.duration = 1.0;
//        keyframeAnimation.beginTime = CACurrentMediaTime() + 2;//设置延迟2秒执行

        tapGesture.view?.layer.addAnimation(keyframeAnimation, forKey: "keyframeAnimation1")

关键帧动画其他可以设置的参数


//keyTimes:各个关键帧的时间控制

//caculationMode:动画计算模式。
kCAAnimationLinear: 线性模式,默认值
kCAAnimationDiscrete: 离散模式
kCAAnimationPaced:均匀处理,会忽略keyTimes
kCAAnimationCubic:平滑执行,对于位置变动关键帧动画运行轨迹更平滑
kCAAnimationCubicPaced:平滑均匀执行

转场效果

转场动画就是从一个场景以动画的形式过渡到另一个场景。转场动画的使用一般分为以下几个步骤:

  • 创建转场动画
  • 设置转场类型、子类型(可选)及其他属性
  • 设置转场后的新视图并添加动画到图层

一个简单专场效果的例子:


        let transfer = CATransition()
        transfer.type = kCATransitionPush//push过渡方式
        transfer.duration = 1
        imageView.image = fetchImage() //获取新的UIImage对象
        imageView.layer.addAnimation(swipeTransition(), forKey: "rightSwipe")//开始转场

转场的效果transfer.type有很多选项,主要选项有

kCATransitionFade:淡入淡出,默认效果
kCATransitionMoveIn:新视图移动到就是图上方
kCATransitionPush:新视图推开旧视图
kCATransitionReveal:移走旧视图然后显示新视图

//苹果未公开的私有转场效果
cube:立方体
suckEffect:吸走的效果
oglFlip:前后翻转效果
rippleEffect:波纹效果
pageCurl:翻页起来
pageUnCurl:翻页下来
cameraIrisHollowOpen:镜头开
cameraIrisHollowClose:镜头关

除了淡入淡出以外,其余三个效果都存在方向性,所以还有个.subType可以设置方向类型

kCATransitionFromRight:
kCATransitionFromLeft:
kCATransitionFromTop:
kCATransitionFromBottom:

下面我们来实现一个淡入淡出切换图片的场景。

  • 左右滑动切换图片
  • 切换的图片和切换效果随机出现

步骤1:添加view底图,添加view的左右滑动手势


    override func viewDidLoad() {
        super.viewDidLoad()

        //背景图片
        let bg = UIImageView(image: UIImage(named: "x1.png"))
        bg.frame = view.frame
        view.addSubview(bg)

        //左右滑动事件
        let rigthSwipe = UISwipeGestureRecognizer(target:self, action:"rightSwipe:")
        rigthSwipe.direction = .Right
        let leftSwipe = UISwipeGestureRecognizer(target:self, action:"leftSwipe:")
        leftSwipe.direction = .Left
        view.addGestureRecognizer(rigthSwipe)
        view.addGestureRecognizer(leftSwipe)

    }

步骤2:随机获取图片和随机获取转场效果的函数


    func fetchImage()->UIImage{
        if images == nil{
            images = [];
            for index in 0...5 {
                let image = UIImage(named: "x" + String(index))
                images.append(image!)
            }
        }
        return images[Int(arc4random()%5)]
    }

    func swipeTransition(subtype:String)->CATransition{
        let transfer = CATransition()
        /*
            kCATransitionFade:淡入淡出,默认效果
            kCATransitionMoveIn:新视图移动到就是图上方
            kCATransitionPush:新视图推开旧视图
            kCATransitionReveal:移走旧视图然后显示新视图

            //苹果未公开的私有转场效果
            cube:立方体
            suckEffect:吸走的效果
            oglFlip:前后翻转效果
            rippleEffect:波纹效果
            pageCurl:翻页起来
            pageUnCurl:翻页下来
            cameraIrisHollowOpen:镜头开
            cameraIrisHollowClose:镜头关
        */
        let types = [kCATransitionFade,kCATransitionMoveIn,kCATransitionPush,kCATransitionReveal,"cube","suckEffect","oglFlip","rippleEffect","pageCurl","pageUnCurl","cameraIrisHollowOpen","cameraIrisHollowClose"]
        let type = types[Int(arc4random()%11)]
        transfer.type = type
        NSLog("%@", type)
        transfer.subtype = subtype
        transfer.duration = 1
        return transfer
    }

步骤3:左右滑动方法,实现场景切换


      func rightSwipe(gesture:UISwipeGestureRecognizer){
          bg.image = fetchImage()
          bg.layer.addAnimation(swipeTransition(kCATransitionFromRight), forKey: "rightSwipe")

      }

      func leftSwipe(gesture:UISwipeGestureRecognizer){
          bg.image = fetchImage()
          bg.layer.addAnimation(swipeTransition(kCATransitionFromLeft), forKey: "leftSwipe")
      }

完成后效果图如下:

demo



本文的demo下载

本文的代码对于的文档名:

  • QuickExampleViewController.swift
  • BasicAnimationViewController.swift
  • KeyFrameAnimationViewController.swift
  • TransferAnimationViewController.swift

感谢收看,如果对大家有帮助,请github上follow和star,本文发布在刘彦玮的技术博客,转载请注明出处

参考文章

原文:大专栏  iOS动画和特效(一)UIView动画和CoreAnimation

原文地址:https://www.cnblogs.com/petewell/p/11422356.html

时间: 2024-10-10 07:45:14

iOS动画和特效(一)UIView动画和CoreAnimation的相关文章

iOS动画开发之二——UIView动画执行的另一种方式

iOS动画开发之二--UIView动画执行的另一种方式 上一篇博客中介绍了UIView的一些常用动画,通过block块,我们可以很方便简洁的创建出动画效果:http://my.oschina.net/u/2340880/blog/484457,这篇博客再介绍一种更加传统的执行UIView的动画的方法. 这种方式相比如block的方式,显得要麻烦一些,apple官方也推荐我们使用带block的创建动画的方式,我们可以将编程重心更多的放在动画逻辑的实现上.使用begin和commit方式主要分为三个

[iOS UI进阶 - 6.3] UIView 动画

1.UIView转场过渡动画   1 // 2 // ViewController.m 3 // UIViewAnimationTest 4 // 5 // Created by hellovoidworld on 15/1/16. 6 // Copyright (c) 2015年 hellovoidworld. All rights reserved. 7 // 8 9 #import "ViewController.h" 10 11 @interface ViewControlle

iOS-UIView动画

今天的主题是UIView的动画. 在iOS中UIView的动画是基于CALayer动画封装. 动画就是静态的图片通过一定频率显示,给人们动画的效果. UIView动画有基于类方法的实现和基于Block方法块的实现. 一.UIView基于类方法的实现的使用 类方法列表: @interface UIView(UIViewAnimation) + (void)beginAnimations:(NSString *)animationID context:(void *)context; // addi

UIView 动画

 UIView 动画 1.动画的作用 提高用户体验, 合理使用动画 2.动画的分类 a.UIView动画, 基于CALayer动画, 是对CALayer动画的封装 i.属性动画 ii.过渡动画 b.CAlayer动画 i.基本动画 ii.关键帧动画 iii.过渡动画 iv.组动画 3.UIView动画是对UIview(或子类)做的动画 a.属性动画和过渡动画都分了两种写法(动画块, block) b.属性动画和过渡动画可以同时执行 4.什么是CALayer? 用于控制渲染和展示内容 UIView

iOS核心动画以及UIView动画的介绍

我们看到很多App带有绚丽狂拽的特效,别出心裁的控件设计,很大程度上提高了用户体验,在增加了实用性的同时,也赋予了app无限的生命力.这些华丽的效果很多都是基于iOS的核心动画原理实现的,本文介绍一些iOS开发中最基本的动画效果实现,掌握了基本属性,才可以绘制出更华丽的效果. 一.概念扩充  1.核心动画: Core Animation,它是一组非常强大的动画处理API,使用它能做出非常炫丽的动画效果,而且往往是事半功倍. Core Animation可以用在Mac OS X和iOS平台.在iO

iOS动画1 — UIView动画

iOS动画1 — UIView动画 iOS动画基础是Core Animation核心动画.Core Animation是iOS平台上负责图形渲染与动画的基础设施.由于核心动画的实现比较复杂,苹果提供了实现简单动画的接口—UIView动画.UIView动画封装在UIView的Category中,主要实现一些简单和常用的动画.UIView动画是对核心动画进行了一层封装,所以最终动画还是通过Core Animation的接口实现. 主要的动画效果都可以通过UIView动画和Core Animation

【iOS开发】---- UIView动画

iOS 动画UIView动画 原文:http://www.cocoachina.com/bbs/read.php?tid=110168 1.概述 UIKit直接将动画集成到UIView类中,实现简单动画的创建过程.UIView类定义了几个内在支持动画的属性声明,当这些属性发生改变时,视图为其变化过程提供内建的动画支持. 执行动画所需要的工作由UIView类自动完成,但仍要在希望执行动画时通知视图,为此需要将改变属性的代码包装到一个代码块中. 2.UIView动画具体创建方法 - (void)bu

iOS动画:UIView动画和CALayer动画(CABasicAnimation、CAKeyframeAnimation的使用)

iOS中的动画有两种实现方式,一种是UIView来实现动画,另一种动画是通过CALayer来实现,下面介绍两种动画的简单实现: 一.UIView动画的实现 UIView使用Context来实现动画 关键代码: //参数1 动画名称 参数2 要实现动画的对象上下文          [UIView beginAnimations:@"attribute" context:_showImageView];          //设置动画的时间     [UIView setAnimatio

ios中layer动画和UIView动画代码总结

kCATransitionFade淡出 kCATransitionMoveIn覆盖原图 kCATransitionPush推出 kCATransitionReveal底部显出来 pageCurl   向上翻一页 pageUnCurl 向下翻一页 rippleEffect 滴水效果 suckEffect 收缩效果,如一块布被抽走 cube 立方体效果 oglFlip 上下翻转效果 #pragma mark UIView 动画 - (IBAction)pressClick1:(id)sender {