Swift:CALayer+Extension

作者: IIronMan | 来源:发表于2020-11-27 15:52 被阅读0次

    JKSwiftExtension,测试用例在 CALayerExtensionViewController 里面
    目录:
    1、自定义链式编程
    2、有关 CABasicAnimation 动画的扩展
    3、有关 CAKeyframeAnimation 动画的扩展
    4、有关 CATransition 动画的扩展
    5、有关 CASpringAnimation 弹簧动画的扩展
    6、有关 CAAnimationGroup 动画组的扩展

    一、自定义链式编程
    // MARK:- 一、自定义链式编程
    public extension CALayer {
    
        // MARK: 1.1、设置圆角
        /// 设置圆角
        /// - Parameter cornerRadius: 圆角
        /// - Returns: 返回自身
        @discardableResult
        func corner(_ cornerRadius: CGFloat) -> Self {
            self.cornerRadius = cornerRadius
            masksToBounds = true
            return self
        }
    
        // MARK: 1.2、设置背景色
        /// 设置背景色
        /// - Parameter color: 背景色
        /// - Returns: 返回自身
        @discardableResult
        func backgroundColor(_ color: UIColor) -> Self {
            backgroundColor = color.cgColor
            return self
        }
    
        // MARK: 1.3、设置背景色 (十六进制字符串)
        /// 设置背景色 (十六进制字符串)
        /// - Parameter hex: 背景色 (十六进制字符串)
        /// - Returns: 返回自身
        @discardableResult
        func backgroundColor(_ hex: String) -> Self {
            backgroundColor = UIColor.hexStringColor(hexString: hex).cgColor
            return self
        }
    
        // MARK: 1.4、设置frame
        /// 设置frame
        /// - Parameter frame: frame
        /// - Returns: 返回自身
        @discardableResult
        func frame(_ frame: CGRect) -> Self {
            self.frame = frame
            return self
        }
    
        // MARK: 1.5、添加到父视图(UIView)
        /// 添加到父视图
        /// - Parameter superView: 父视图(UIView)
        /// - Returns: 返回自身
        @discardableResult
        func addTo(_ superView: UIView) -> Self {
            superView.layer.addSublayer(self)
            return self
        }
    
        // MARK: 1.6、添加到父视图(CALayer)
        /// 添加到父视图(CALayer)
        /// - Parameter superLayer: 父视图(CALayer)
        /// - Returns: 返回自身
        @discardableResult
        func addTo(_ superLayer: CALayer) -> Self {
            superLayer.addSublayer(self)
            return self
        }
    
        // MARK: 1.7、是否隐藏
        /// 是否隐藏
        /// - Parameter isHidden: 是否隐藏
        /// - Returns: 返回自身
        @discardableResult
        func isHidden(_ isHidden: Bool) -> Self {
            self.isHidden = isHidden
            return self
        }
    
        // MARK: 1.8、设置边框宽度
        /// 设置边框宽度
        /// - Parameter width: 边框宽度
        /// - Returns: 返回自身
        @discardableResult
        func borderWidth(_ width: CGFloat) -> Self {
            self.borderWidth = width
            return self
        }
    
        // MARK: 1.9、设置边框颜色
        /// 设置边框颜色
        /// - Parameter color: 边框颜色
        /// - Returns: 返回自身
        @discardableResult
        func borderColor(_ color: UIColor) -> Self {
            self.borderColor = color.cgColor
            return self
        }
    
        // MARK: 1.10、是否开启光栅化
        /// 是否开启光栅化
        /// - Parameter rasterize: 是否开启光栅化
        /// - Returns: 返回自身
        @discardableResult
        func shouldRasterize(_ rasterize: Bool) -> Self {
            self.shouldRasterize = rasterize
            return self
        }
    
        // MARK: 1.11、设置光栅化比例
        /// 设置光栅化比例
        /// - Parameter scale: 光栅化比例
        /// - Returns: 返回自身
        @discardableResult
        func rasterizationScale(_ scale: CGFloat) -> Self {
            self.rasterizationScale = scale
            self.shouldRasterize = true
            return self
        }
    
        // MARK: 1.12、设置阴影颜色
        /// 设置阴影颜色
        /// - Parameter color: 阴影颜色
        /// - Returns: 返回自身
        @discardableResult
        func shadowColor(_ color: UIColor) -> Self {
            self.shadowColor = color.cgColor
            return self
        }
    
        // MARK: 1.13、设置阴影的透明度,取值范围:0~1
        /// 设置阴影的透明度,取值范围:0~1
        /// - Parameter opacity: 阴影的透明度
        /// - Returns: 返回自身
        @discardableResult
        func shadowOpacity(_ opacity: Float) -> Self {
            self.shadowOpacity = opacity
            return self
        }
    
        // MARK: 1.14、设置阴影的偏移量
        /// 设置阴影的偏移量
        /// - Parameter offset: 偏移量
        /// - Returns: 返回自身
        @discardableResult
        func shadowOffset(_ offset: CGSize) -> Self {
            self.shadowOffset = offset
            return self
        }
    
        // MARK: 1.15、设置阴影圆角
        /// 设置阴影圆角
        /// - Parameter radius: 圆角大小
        /// - Returns: 返回自身
        @discardableResult
        func shadowRadius(_ radius: CGFloat) -> Self {
            self.shadowRadius = radius
            return self
        }
    
        // MARK: 1.16、高性能添加阴影路径 Shadow Path,提示:当用bounds设置path时,看起来的效果与只设置了shadowOpacity一样,但是添加了shadowPath后消除了离屏渲染问题
        /// 高性能添加阴影 Shadow Path
        /// - Parameter path: 阴影Path
        /// - Returns: 返回自身
        @discardableResult
        func shadowPath(_ path: CGPath) -> Self {
            self.shadowPath = path
            return self
        }
    }
    
    二、有关 CABasicAnimation 动画的扩展
    // MARK:- 二、有关 CABasicAnimation 动画的扩展
    public extension CALayer {
    
        // MARK: 2.1、移动到另外一个 点(point)
        /// 从一个 点(point) 移动到另外一个 点(poi
        /// - Parameters:
        ///   - endPoint: 终点
        ///   - duration: 持续时间
        ///   - delay: 几秒后执行
        ///   - repeatNumber: 重复次数
        ///   - removedOnCompletion: 运动后的位置保持不变(layer的最后位置是toValue)
        ///   - option: 动画的时间节奏控制 方式
        func animationMovePoint(to endPoint: CGPoint,
                                duration: TimeInterval,
                                delay: TimeInterval = 0,
                                repeatNumber: Float = 1,
                                removedOnCompletion: Bool = false,
                                option: CAMediaTimingFunctionName = .default) {
            baseBasicAnimation(keyPath: "position", startValue: position, endValue: endPoint, duration: duration, delay: delay, repeatNumber: repeatNumber, removedOnCompletion: removedOnCompletion, option: option)
        }
    
        // MARK: 2.2、移动X
        /// 移动X
        /// - Parameters:
        ///   - moveValue: 移动到的X值
        ///   - duration:  动画持续的时间
        ///   - removedOnCompletion: 运动后的位置保持不变(layer的最后位置是toValue)
        ///   - option: 动画的时间节奏控制 方式
        func animationMoveX(moveValue: Any?,
                            duration: TimeInterval = 2.0,
                            delay: TimeInterval = 0,
                            repeatNumber: Float = 1,
                            removedOnCompletion: Bool = false,
                            option: CAMediaTimingFunctionName = .default) {
            baseBasicAnimation(keyPath: "transform.translation.x", startValue: position, endValue: moveValue, duration: duration, delay: delay, repeatNumber: repeatNumber, removedOnCompletion: removedOnCompletion, option: option)
        }
    
        // MARK: 2.3、移动Y
        /// 移动Y
        /// - Parameters:
        ///   - moveValue: 移动到的Y值
        ///   - duration:  动画持续的时间
        ///   - removedOnCompletion: 运动后的位置保持不变(layer的最后位置是toValue)
        ///   - option: 动画的时间节奏控制 方式
        func animationMoveY(moveValue: Any?,
                            duration: TimeInterval = 2.0,
                            delay: TimeInterval = 0,
                            repeatNumber: Float = 1,
                            removedOnCompletion: Bool = false,
                            option: CAMediaTimingFunctionName = .default) {
            baseBasicAnimation(keyPath: "transform.translation.y", startValue: position, endValue: moveValue, duration: duration, delay: delay, repeatNumber: repeatNumber, removedOnCompletion: removedOnCompletion, option: option)
        }
    
        // MARK: 2.4、圆角动画
        /// 圆角动画
        /// - Parameters:
        ///   - cornerRadius: 圆角大小
        ///   - duration:  动画持续的时间
        ///   - removedOnCompletion: 运动后的位置保持不变(layer的最后位置是toValue)
        ///   - option: 动画的时间节奏控制 方式
        func animationCornerRadius(cornerRadius: Any?,
                                   duration: TimeInterval = 2.0,
                                   delay: TimeInterval = 0,
                                   repeatNumber: Float = 1,
                                   removedOnCompletion: Bool = false,
                                   option: CAMediaTimingFunctionName = .default) {
            baseBasicAnimation(keyPath: "cornerRadius", startValue: position, endValue: cornerRadius, duration: duration, delay: delay, repeatNumber: repeatNumber, removedOnCompletion: removedOnCompletion, option: option)
        }
    
        // MARK: 2.5、缩放动画
        /// 缩放动画
        /// - Parameters:
        ///   - scaleValue: 放大的倍数
        ///   - duration:  动画持续的时间
        ///   - removedOnCompletion: 运动后的位置保持不变(layer的最后位置是toValue)
        ///   - option: 动画的时间节奏控制 方式
        func animationScale(scaleValue: Any?,
                            duration: TimeInterval = 2.0,
                            delay: TimeInterval = 0,
                            repeatNumber: Float = 1,
                            removedOnCompletion: Bool = true,
                            option: CAMediaTimingFunctionName = .default) {
            baseBasicAnimation(keyPath: "transform.scale", startValue: 1, endValue: scaleValue, duration: duration, delay: delay, repeatNumber: repeatNumber, removedOnCompletion: removedOnCompletion, option: option)
        }
    
        // MARK: 2.6、旋转动画
        /// 缩放动画
        /// - Parameters:
        ///   - rotation: 旋转的角度
        ///   - duration:  动画持续的时间
        ///   - removedOnCompletion: 运动后的位置保持不变(layer的最后位置是toValue)
        ///   - option: 动画的时间节奏控制 方式
        func animationRotation(rotation: Any?,
                               duration: TimeInterval = 2.0,
                               delay: TimeInterval = 0,
                               repeatNumber: Float = 1,
                               removedOnCompletion: Bool = true,
                               option: CAMediaTimingFunctionName = .default) {
            baseBasicAnimation(keyPath: "transform.rotation", startValue: nil, endValue: rotation, duration: duration, delay: delay, repeatNumber: repeatNumber, removedOnCompletion: removedOnCompletion, option: option)
        }
    
        // MARK: CABasicAnimation 动画的基础方法
        /// 动画的 X/Y 移动
        /// - Parameters:
        ///   - keyPath: 动画的类型
        ///   - moveValue: 移动到的位置
        ///   - duration:  动画持续的时间
        ///   - repeatNumber: 重复的次数
        ///   - removedOnCompletion: 运动后的位置保持不变(layer的最后位置是toValue)
        ///   - option: 动画的时间节奏控制 方式
        func baseBasicAnimation(keyPath: String,
                                startValue: Any?,
                                endValue: Any?,
                                duration: TimeInterval = 2.0,
                                delay: TimeInterval = 0,
                                repeatNumber: Float = 1,
                                removedOnCompletion: Bool = false,
                                option: CAMediaTimingFunctionName = .default) {
            let translatonAnimation: CABasicAnimation = CABasicAnimation()
            // 几秒后执行
            translatonAnimation.beginTime = CACurrentMediaTime() + delay
            // 动画的类型
            translatonAnimation.keyPath = keyPath
            // 起始的值
            if let weakStartValue = startValue {
                translatonAnimation.fromValue = weakStartValue
            }
            // 结束的值
            translatonAnimation.toValue = endValue
            // 动画持续的时间
            translatonAnimation.duration = duration
            // 运动后的位置保持不变(layer的最后位置是toValue)
            translatonAnimation.isRemovedOnCompletion = removedOnCompletion
            // 图层保持动画执行后的状态,前提是fillMode设置为kCAFillModeForwards
            translatonAnimation.fillMode = CAMediaTimingFillMode.forwards
            /**
             linear: 匀速
             easeIn: 慢进
             easeOut: 慢出
             easeInEaseOut: 慢进慢出
             default: 慢进慢出
             */
            translatonAnimation.timingFunction = CAMediaTimingFunction(name: option)
            add(translatonAnimation, forKey: nil)
        }
    }
    
    三、有关 CAKeyframeAnimation 动画的扩展
    // MARK:- 三、有关 CAKeyframeAnimation 动画的扩展
    public extension CALayer {
    
        // MARK: 3.1、设置values使其沿 position 运动 (这里移动是以 视图的 锚点移动的,默认是视图的 中心点)
        /// 设置values使其沿 position 运动 (这里移动是以 视图的 锚点移动的,默认是视图的 中心点)
        /// - Parameters:
        ///   - values: CGPoint 点
        ///   - keyTimes: 设置关键帧对应的时间点,范围:0-1。如果没有设置该属性,则每一帧的时间平分。
        ///   - duration: 动画持续的时间
        ///   - repeatNumber: 重复的次数
        ///   - removedOnCompletion: 运动后的位置保持不变(layer的最后位置是toValue)
        ///   - option: 动画的时间节奏控制 方式
        func addKeyframeAnimationPosition(values: [Any],
                                          keyTimes: [NSNumber]?,
                                          duration: TimeInterval = 2.0,
                                          delay: TimeInterval = 0,
                                          repeatNumber: Float = 1,
                                          removedOnCompletion: Bool = false,
                                          option: CAMediaTimingFunctionName = .default) {
            baseKeyframeAnimation(keyPath: "position", values: values, keyTimes: keyTimes, duration: duration, delay: delay, repeatNumber: repeatNumber, path: nil, removedOnCompletion: removedOnCompletion, option: option)
        }
    
        // MARK: 3.2、设置 角度值 抖动
        /// 设置 角度值 抖动
        /// - Parameters:
        ///   - values: CGPoint 点
        ///   - keyTimes: 设置关键帧对应的时间点,范围:0-1。如果没有设置该属性,则每一帧的时间平分。
        ///   - duration: 动画持续的时间
        ///   - repeatNumber: 重复的次数
        ///   - removedOnCompletion: 运动后的位置保持不变(layer的最后位置是toValue)
        ///   - option: 动画的时间节奏控制 方式
        func addKeyframeAnimationRotation(values: [Any] = [CGFloat(-5).degreesToRadians(), CGFloat(5).degreesToRadians(), CGFloat(-5).degreesToRadians()],
                                          keyTimes: [NSNumber]?,
                                          duration: TimeInterval = 1.0,
                                          delay: TimeInterval = 0,
                                          repeatNumber: Float = 1,
                                          removedOnCompletion: Bool = true,
                                          option: CAMediaTimingFunctionName = .default) {
            baseKeyframeAnimation(keyPath: "transform.rotation", values: values, keyTimes: keyTimes, duration: duration, delay: delay, repeatNumber: repeatNumber, path: nil, removedOnCompletion: removedOnCompletion, option: option)
        }
    
        // MARK: 3.3、根据 CGPath 进行做 移动 动画
        /// 根据 CGPath 进行做 移动 动画
        /// - Parameters:
        ///   - path: CGPath 路径
        ///   - duration: 动画时长
        ///   - repeatNumber: 重复次数
        ///   - removedOnCompletion: 运动后的位置保持不变(layer的最后位置是toValue)
        ///   - option: 动画的时间节奏控制 方式
        func addKeyframeAnimationPositionBezierPath(path: CGPath?,
                                                    duration: TimeInterval = 2.0,
                                                    delay: TimeInterval = 0,
                                                    repeatNumber: Float = 1,
                                                    removedOnCompletion: Bool = false,
                                                    option: CAMediaTimingFunctionName = .default) {
            baseKeyframeAnimation(keyPath: "position", values: nil, keyTimes: nil, duration: duration,  delay: delay, repeatNumber: repeatNumber, path: path, removedOnCompletion: removedOnCompletion, option: option)
        }
    
        // MARK: CAKeyframeAnimation 动画的通用方法
        /// CAKeyframeAnimation 动画的通用方法
        /// - Parameters:
        ///   - keyPath: 动画路径对象,可以指定一个路径,在执行动画时路径会沿着路径移动,Path在动画中只会影响视图的Position。
        ///   - values: 关键帧数组对象,里面每一个元素即为一个关键帧,动画会在对应的时间段内,依次执行数组中每一个关键帧的动画
        ///   - keyTimes: 设置关键帧对应的时间点,范围:0-1。如果没有设置该属性,则每一帧的时间平分。
        ///   - duration: 动画持续的时间
        ///   - repeatNumber: 重复的次数
        ///   - removedOnCompletion: 运动后的位置保持不变(layer的最后位置是toValue)
        ///   - option: 动画的时间节奏控制 方式
        func baseKeyframeAnimation(keyPath: String,
                                   values: [Any]?,
                                   keyTimes: [NSNumber]?,
                                   duration: TimeInterval = 2.0,
                                   delay: TimeInterval = 0,
                                   repeatNumber: Float = 1,
                                   path: CGPath?,
                                   removedOnCompletion: Bool = false,
                                   option: CAMediaTimingFunctionName = .default) {
            let keyframeAnimation = CAKeyframeAnimation(keyPath: keyPath)
            keyframeAnimation.duration = duration
            // 几秒后执行
            keyframeAnimation.beginTime = CACurrentMediaTime() + delay
            keyframeAnimation.isRemovedOnCompletion = removedOnCompletion
            keyframeAnimation.fillMode = .forwards
            keyframeAnimation.repeatCount = repeatNumber
            // 传进来的值,可以是一组 CGPoint
            if let weakValues = values {
                keyframeAnimation.values = weakValues
            }
            if let weakKeyTimes = keyTimes {
                keyframeAnimation.keyTimes = weakKeyTimes
            }
            if let weakPath = path {
                keyframeAnimation.path = weakPath
                // 计算模式 -> 强制运动,匀速进行,不管路径有多远!否则一次动画结束会有短暂停顿
                keyframeAnimation.calculationMode = .cubicPaced
            }
            // 旋转模式 -> 沿着路径,自行旋转 转的时候需要沿着路径的切线!进行转动!
            // keyframeAnimation.rotationMode = .rotateAuto
            //  动画的时间节奏控制 方式
            keyframeAnimation.timingFunction = CAMediaTimingFunction(name: option)
            add(keyframeAnimation, forKey: nil)
        }
    }
    
    四、有关 CATransition 动画的扩展
    // MARK:- 四、有关 CATransition 动画的扩展
    /**
     转场动画,比UIVIew转场动画具有更多的动画效果,比如Nav的默认Push视图的效果就是通过CATransition的kCATransitionPush类型来实现。
     */
    public extension CALayer {
    
        // MARK: 4.1、转场动画的使用
        /// 转场动画的使用
        /// - Parameters:
        ///   - type: 过渡动画的类型:
        ///   - subtype: 过渡动画的方向
        ///   - duration: 动画的时间
        func addTransition(type: CATransitionType,
                           subtype: CATransitionSubtype?,
                           duration: CFTimeInterval = 2.0,
                           delay: TimeInterval = 0) {
            let transition = CATransition()
            // 几秒后执行
            transition.beginTime = CACurrentMediaTime() + delay
            /**
             过渡动画的类型
             fade: 渐变
             moveIn: 覆盖
             push: 推出
             reveal: 揭开
             还有一些私有动画类型,效果很炫酷,不过不推荐使用。
           私有动画类型的值有:"cube"、"suckEffect"、"oglFlip"、 "rippleEffect"、"pageCurl"、"pageUnCurl"等等
             */
            transition.type = type
            /**
             fromRight: 从右边
             fromLeft:  从左边
             fromTop: 从顶部
             fromBottom: 从底部
             */
            transition.subtype = .fromLeft
            transition.duration = 1
            add(transition, forKey: nil)
        }
    }    
    
    五、有关 CASpringAnimation 弹簧动画的扩展
    // MARK:- 五、有关 CASpringAnimation 弹簧动画的扩展
    /**
     CASpringAnimation是 iOS9 新加入动画类型,是CABasicAnimation的子类,用于实现弹簧动画
     CASpringAnimation和UIView的SpringAnimation对比:
     1.CASpringAnimation 可以设置更多影响弹簧动画效果的属性,可以实现更复杂的弹簧动画效果,且可以和其他动画组合。
     2.UIView的SpringAnimation实际上就是通过CASpringAnimation来实现。
     */
    public extension CALayer {
    
        // MARK: 5.1、弹簧动画:Bounds 动画
        /// 弹簧动画
        /// - Parameters:
        ///   - mass: 质量(影响弹簧的惯性,质量越大,弹簧惯性越大,运动的幅度越大)
        ///   - stiffness: 弹性系数(弹性系数越大,弹簧的运动越快)
        ///   - damping: 阻尼系数(阻尼系数越大,弹簧的停止越快)
        ///   - initialVelocity: 初始速率(弹簧动画的初始速度大小,弹簧运动的初始方向与初始速率的正负一致,若初始速率为0,表示忽略该属性)
        ///   - repeatNumber: 动画执行的次数
        ///   - removedOnCompletion: 运动后的位置保持不变(layer的最后位置是toValue)
        ///   - option: 动画的时间节奏控制 方式
        func addSpringAnimationBounds(toValue: Any?,
                                      delay: TimeInterval = 0,
                                      mass: CGFloat = 10.0,
                                      stiffness: CGFloat = 5000,
                                      damping: CGFloat = 100.0,
                                      initialVelocity: CGFloat = 5,
                                      repeatNumber: Float = 1,
                                      removedOnCompletion: Bool = false,
                                      option: CAMediaTimingFunctionName = .default) {
            baseSpringAnimation(path: "bounds", toValue: toValue, mass: mass, stiffness: stiffness, damping: damping, initialVelocity: initialVelocity, repeatNumber: repeatNumber, removedOnCompletion: removedOnCompletion, option: option)
        }
    
        // MARK: 弹簧的基类动画
        ///  弹簧的基类动画
        /// - Parameters:
        ///   - path: 动画路径对象,可以指定一个路径,在执行动画时路径会沿着路径移动
        ///   - mass: 质量(影响弹簧的惯性,质量越大,弹簧惯性越大,运动的幅度越大)
        ///   - stiffness: 弹性系数(弹性系数越大,弹簧的运动越快)
        ///   - damping: 阻尼系数(阻尼系数越大,弹簧的停止越快)
        ///   - initialVelocity: 初始速率(弹簧动画的初始速度大小,弹簧运动的初始方向与初始速率的正负一致,若初始速率为0,表示忽略该属性)
        ///   - repeatNumber: 动画执行的次数
        ///   - removedOnCompletion: 运动后的位置保持不变(layer的最后位置是toValue)
        ///   - option: 动画的时间节奏控制 方式
        func baseSpringAnimation(path: String?,
                                 toValue: Any?,
                                 delay: TimeInterval = 0,
                                 mass: CGFloat = 10.0,
                                 stiffness: CGFloat = 5000,
                                 damping: CGFloat = 100.0,
                                 initialVelocity: CGFloat = 5,
                                 repeatNumber: Float = 1,
                                 removedOnCompletion: Bool = false,
                                 option: CAMediaTimingFunctionName = .default) {
            let springAnimation = CASpringAnimation(keyPath: path)
            // 几秒后执行
            springAnimation.beginTime = CACurrentMediaTime() + delay
            // 质量,影响图层运动时的弹簧惯性,质量越大,弹簧拉伸和压缩的幅度越大
            springAnimation.mass = mass
            // 刚度系数(劲度系数/弹性系数),刚度系数越大,形变产生的力就越大,运动越快
            springAnimation.stiffness = stiffness
            // 阻尼系数,阻止弹簧伸缩的系数,阻尼系数越大,停止越快
            springAnimation.damping = damping
            // 初始速率,动画视图的初始速度大小;速率为正数时,速度方向与运动方向一致,速率为负数时,速度方向与运动方向相反
            springAnimation.initialVelocity = initialVelocity
            // settlingDuration:结算时间(根据动画参数估算弹簧开始运动到停止的时间,动画设置的时间最好根据此时间来设置)
            springAnimation.duration = springAnimation.settlingDuration
            springAnimation.toValue = toValue
            springAnimation.isRemovedOnCompletion = removedOnCompletion
            springAnimation.fillMode = CAMediaTimingFillMode.forwards
            // 动画的时间节奏控制 方式
            springAnimation.timingFunction = CAMediaTimingFunction(name: option)
            add(springAnimation, forKey: nil)
        }
    }
    
    六、有关 CAAnimationGroup 动画组的扩展
    // MARK:- 六、有关 CAAnimationGroup 动画组的扩展
    /**
     使用Group可以将多个动画合并一起加入到层中,Group中所有动画并发执行,可以方便地实现需要多种类型动画的场景
     */
    public extension CALayer {
    
        // MARK: CAAnimationGroup 的基类动画
        /// CAAnimationGroup 的基类动画
        /// - Parameters:
        ///   - animations: 动画组
        ///   - duration: 动画时长
        ///   - repeatNumber: 重复次数
        ///   - removedOnCompletion: 运动后的位置保持不变(layer的最后位置是toValue)
        ///   - option: 动画的时间节奏控制 方式
        func baseAnimationGroup(animations: [CAAnimation]?,
                                duration: TimeInterval = 2.0,
                                delay: TimeInterval = 0,
                                repeatNumber: Float = 1,
                                removedOnCompletion: Bool = false,
                                option: CAMediaTimingFunctionName = .default) {
            let animationGroup = CAAnimationGroup()
            // 几秒后执行
            animationGroup.beginTime = CACurrentMediaTime() + delay
            animationGroup.animations = animations
            animationGroup.duration = duration
            animationGroup.fillMode = .forwards;
            animationGroup.isRemovedOnCompletion = removedOnCompletion
            // 动画的时间节奏控制 方式
            animationGroup.timingFunction = CAMediaTimingFunction(name: option)
            add(animationGroup, forKey: nil)
        }
    }
    

    相关文章

      网友评论

        本文标题:Swift:CALayer+Extension

        本文链接:https://www.haomeiwen.com/subject/uopxwktx.html