iOS动画

CAKeyframeAnimation

2018-03-26  本文已影响0人  Neal_f

CAKeyframeAnimation

  1. 认识CAKeyframeAnimation

    CAKeyframeAnimation是可以在layer层按照一组关键帧执行的动画。

  2. 属性介绍

keyPath : 动画的关键路径属性(做什么动画)

path : 基于点的属性的路径,对于包含CGPoint数据类型的层属性,您分配给该属性的路径对象定义了该属性在动画长度上的值。如果指定此属性的值,则忽略值属性中的任何数据

values:关键帧值表示动画必须执行的值,此属性中的值仅在path属性的值为nil时才使用。根据属性的类型,您可能需要用NSValue对象的NSNumber包装这个数组中的值。对于一些核心图形数据类型,您可能还需要将它们转换为id,然后再将它们添加到数组中。将给定的关键帧值应用于该层的时间取决于动画时间,由calculationMode、keyTimes和timingFunctions属性控制。关键帧之间的值是使用插值创建的,除非将计算模式设置为kcaanimation离散

duration : 动画时长

repeatCount : 重复次数

calculationMode : 动画计算方式

kCAAnimationLinear : 默认差值

kCAAnimationDiscrete : 逐帧显示

kCAAnimationPaced : 匀速 无视keyTimes

kCAAnimationCubic : keyValue之间曲线平滑 可用 tensionValues,continuityValues,biasValues 调整

kCAAnimationCubicPaced : keyValue之间平滑差值 无视keyTimes

KeyTimes : 一个可选的NSNumber对象数组,它定义了给定关键帧片段的时间

timingFunctions:一个可选的CAMediaTimingFunction对象数组,它定义每个关键帧段的节奏

kCAMediaTimingFunctionLinear:线性起搏,使动画在其持续时间内均匀地发生

kCAMediaTimingFunctionEaseIn:使一个动画开始缓慢,然后加速,随着它的进程

kCAMediaTimingFunctionEaseOut: 使动画快速开始,然后缓慢地进行

kCAMediaTimingFunctionEaseInEaseOut:使动画开始缓慢,在其持续时间的中间加速,然后在完成之前再放慢速度

kCAMediaTimingFunctionDefault: 默认,确保动画的时间与大多数系统动画的匹配

rotationMode : 旋转方式

kCAAnimationRotateAuto : 自动

kCAAnimationRotateAutoReverse : 自动翻转 不设置则不旋转

  1. 示例



import UIKit
import CoreGraphics
import QuartzCore


//使用关键帧动画

class Style1Button: UIButton {

    var top: CAShapeLayer! = CAShapeLayer()
    var bottom: CAShapeLayer! = CAShapeLayer()
    var middle: CAShapeLayer! = CAShapeLayer()
    
    //keyframe
    let shortStrokeTop1 = UIBezierPath().then { (line) in
        line.move(to: CGPoint(x: 10, y: 16))
        line.addLine(to: CGPoint(x: 34, y: 16))
    }
    let shortStrokeTop2 = UIBezierPath().then { (line) in
        line.move(to: CGPoint(x: 10, y: 17.5))
        line.addLine(to: CGPoint(x: 30, y: 16))
    }
    let shortStrokeTop3 = UIBezierPath().then { (line) in
        line.move(to: CGPoint(x: 10, y: 19))
        line.addLine(to: CGPoint(x: 26, y: 17))
    }
    let shortStrokeTop4 = UIBezierPath().then { (line) in
        line.move(to: CGPoint(x: 10, y: 20.5))
        line.addLine(to: CGPoint(x: 22, y: 18))
    }
    let shortStrokeTop5 = UIBezierPath().then { (line) in
        line.move(to: CGPoint(x: 10, y: 22))
        line.addLine(to: CGPoint(x: 18, y: 19))
    }
    
    let shortStrokeBottom1 = UIBezierPath().then { (line) in
        line.move(to: CGPoint(x: 10, y: 28))
        line.addLine(to: CGPoint(x: 34, y: 28))
    }
    let shortStrokeBottom2 = UIBezierPath().then { (line) in
        line.move(to: CGPoint(x: 10, y: 26.5))
        line.addLine(to: CGPoint(x: 30, y: 28))
    }
    let shortStrokeBottom3 = UIBezierPath().then { (line) in
        line.move(to: CGPoint(x: 10, y: 25))
        line.addLine(to: CGPoint(x: 26, y: 27))
    }
    let shortStrokeBottom4 = UIBezierPath().then { (line) in
        line.move(to: CGPoint(x: 10, y: 23.5))
        line.addLine(to: CGPoint(x: 22, y: 26))
    }
    let shortStrokeBottom5 = UIBezierPath().then { (line) in
        line.move(to: CGPoint(x: 10, y: 22))
        line.addLine(to: CGPoint(x: 18, y: 25))
    }
    
    let shortStrokeMiddle1 = UIBezierPath().then { (line) in
        line.move(to: CGPoint(x: 10, y: 22))
        line.addLine(to: CGPoint(x: 34, y: 22))
    }
    
    let shortStrokeMiddle2 = UIBezierPath().then { (line) in
        line.move(to: CGPoint(x: 10, y: 22))
        line.addLine(to: CGPoint(x: 30, y: 22))
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        self.top.path = shortStrokeTop1.cgPath
        self.middle.path = shortStrokeMiddle1.cgPath
        self.bottom.path = shortStrokeBottom1.cgPath
        
        for layer in [self.top,self.middle,self.bottom] {
            layer?.fillColor = nil
            layer?.strokeColor = UIColor.white.cgColor
            layer?.lineWidth = 2
            layer?.miterLimit = 4
            layer?.lineCap = kCALineCapRound
            layer?.bounds = (layer?.path?.boundingBox)!
            self.layer.addSublayer(layer!)
        }

        self.top.position = CGPoint(x: 22, y: 16)
        self.middle.position = CGPoint(x: 22, y: 22)
        self.bottom.position = CGPoint(x: 22, y: 28)
    }
    
    var showsMenu: Bool = false {
        didSet {
          
            if showsMenu {
                
                let topValues = [shortStrokeTop1.cgPath,shortStrokeTop2.cgPath,shortStrokeTop3.cgPath,shortStrokeTop4.cgPath,shortStrokeTop5.cgPath]
                self.top.add(pathAnimation(topValues), forKey: "TopPath")
                
                let bottomValues = [shortStrokeBottom1.cgPath,shortStrokeBottom2.cgPath,shortStrokeBottom3.cgPath,shortStrokeBottom4.cgPath,shortStrokeBottom5.cgPath]
                self.bottom.add(pathAnimation(bottomValues), forKey: "BottomPath")
                
                let middleValues = [shortStrokeMiddle1.cgPath,shortStrokeMiddle2.cgPath]
                self.middle.add(pathAnimation(middleValues), forKey: "MiddlePath")
                
            }else {
                
                let topValues = Array([shortStrokeTop1.cgPath,shortStrokeTop2.cgPath,shortStrokeTop3.cgPath,shortStrokeTop4.cgPath,shortStrokeTop5.cgPath].reversed())
                self.top.add(pathAnimation(topValues), forKey: "TopPathReversed")
                
                let bottomValues = Array([shortStrokeBottom1.cgPath,shortStrokeBottom2.cgPath,shortStrokeBottom3.cgPath,shortStrokeBottom4.cgPath,shortStrokeBottom5.cgPath].reversed())
                self.bottom.add(pathAnimation(bottomValues), forKey: "BottomPathReversed")
                
                let middleValues = Array([shortStrokeMiddle1.cgPath,shortStrokeMiddle2.cgPath].reversed())
                self.middle.add(pathAnimation(middleValues), forKey: "MiddlePathReversed")
                
                
            }
        }
        
    }
    
    
    func pathAnimation(_ values: [CGPath]) ->CAKeyframeAnimation {
        
        let pathAnimation = CAKeyframeAnimation(keyPath: "path")
        pathAnimation.values = values
        pathAnimation.duration = 0.5
        pathAnimation.isRemovedOnCompletion = false
        pathAnimation.fillMode = kCAFillModeForwards
        pathAnimation.beginTime = 0
        pathAnimation.timingFunctions = [CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)]
        pathAnimation.repeatCount = 1
        return pathAnimation
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
}

上一篇 下一篇

猜你喜欢

热点阅读