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)
}
}
网友评论