一.组动画的创建
首先创建一个组动画,也就是大小变化和透明度变化的动画。
// 大小变化
let scaleAnimation = CAKeyframeAnimation(keyPath: "transform.scale")
scaleAnimation.keyTimes = [0, 0.5, 1]
scaleAnimation.values = [1, 0.4, 1]
scaleAnimation.duration = duration
// 透明度变化
let opacityAnimaton = CAKeyframeAnimation(keyPath: "opacity")
//该属性是一个数组,用以指定每个子路径的时间。
opacityAnimaton.keyTimes = [0, 0.5, 1]
//values属性指明整个动画过程中的关键帧点,需要注意的是,起点必须作为values的第一个值。
opacityAnimaton.values = [1, 0.3, 1]
opacityAnimaton.duration = duration
// 组动画
let animation = CAAnimationGroup()
//将大小变化和透明度变化的动画加入到组动画
animation.animations = [scaleAnimation, opacityAnimaton]
//动画的过渡效果
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
//动画的持续时间
animation.duration = duration
//设置重复次数,HUGE可看做无穷大,起到循环动画的效果
animation.repeatCount = HUGE
//运行一次是否移除动画
animation.removedOnCompletion = false
需要注意的是上面的animation.timingFunction
是动画的过渡效果,里面有这几种,你可以根据自己的需求选择
1. kCAMediaTimingFunctionLinear
//线性
2. kCAMediaTimingFunctionEaseIn
//淡入
3. kCAMediaTimingFunctionEaseOut
//淡出
4. kCAMediaTimingFunctionEaseInEaseOut
//淡入淡出
5. kCAMediaTimingFunctionDefault
//默认
二.创建圆形图层
// Draw circles
for var i = 0; i < 8; i++ {
let circle = creatCircle(angle: CGFloat(M_PI_4 * Double(i)),
size: circleSize,
origin: CGPoint(x: x, y: y + 50),
containerSize: size,
color: color)
animation.beginTime = beginTime + beginTimes[i]
circle.addAnimation(animation, forKey: "animation")
layer.addSublayer(circle)
}
这里面是创建了八个小圆,将组动画赋予这八个圆,并添加在这个视图的Layer上,creatCircle
创图层的这个方法如下
func creatCircle(# angle: CGFloat, size: CGFloat, origin: CGPoint, containerSize: CGSize, color: UIColor) -> CALayer {
let radius = containerSize.width/2
let circle = createLayerWith(size: CGSize(width: size, height: size), color: color)
let frame = CGRect(
x: origin.x + radius * (cos(angle) + 1) - size / 2,
y: origin.y + radius * (sin(angle) + 1) - size / 2,
width: size,
height: size)
circle.frame = frame
return circle
}
上面angle
,size
,origin
,containerSize
,color
,都是传入的参数,-> CALayer
这个在Swift中代表的是返回类型,这里的返回类型就是CALayer
,不像在OC中返回类型写在方法的前面- (CALayer *) ...
这里func creatCircle(# angle: CGFloat,
里面有#
,代表的就是在函数(或者方法)的参数名前添加”#”,可以使该参数拥有相同的本地参数名和外部参数名。(注:在方法中,第二个及后续的参数,默认是具有和内部参数一致的外部参数名的,只有第一个参数没有,可以使用”#”符号来强制给第一个参数添加与本地参数名一致的外部参数名,但是不推荐。)
三.创建CAShapeLayer
也就是上面的createLayerWith
这个方法,如下
func createLayerWith(# size: CGSize, color: UIColor) -> CALayer {
//创建CAShapeLayer,如果对CAShapeLayer比较陌生,简单介绍下CAShapeLayer
let layer: CAShapeLayer = CAShapeLayer()
//创建贝塞尔曲线路径(CAShapeLayer就依靠这个路径渲染)
var path: UIBezierPath = UIBezierPath()
//addArcWithCenter,顾名思义就是根据中心点画圆(OC语法的命名优越感又体现出来了0.0),这几个参数
/**
center: CGPoint 中心点
radius: CGFloat 半径
startAngle: CGFloat 起始的弧度
endAngle: CGFloat 结束的弧度
clockwise: Bool 绘画方向 true:顺时针 false:逆时针
*/
path.addArcWithCenter(CGPoint(x: size.width / 2, y: size.height / 2),
radius: size.width / 2,
startAngle: 0,
endAngle: CGFloat(2 * M_PI),
clockwise: false);
//线宽,如果画圆填充的话也可以不设置
layer.lineWidth = 2
//填充颜色,这里也就是圆的颜色
layer.fillColor = color.CGColor
//图层背景色
layer.backgroundColor = nil
//把贝塞尔曲线路径设为layer的渲染路径
layer.path = path.CGPath
return layer;
}
CAShapeLayer
是一个通过矢量图形而不是bitmap
来绘制的图层子类。你指定诸如颜色和线宽等属性,用CGPath
来定义想要绘制的图形,最后CAShapeLayer
就自动渲染出来了。当然,你也可以用Core Graphics
直接向原始的CALyer
的内容中绘制一个路径,相比直下,使用CAShapeLayer
有以下一些优点:
- 渲染快速。
CAShapeLayer
使用了硬件加速,绘制同一图形会比用Core Graphics
快很多。 - 高效使用内存。一个
CAShapeLayer
不需要像普通CALayer一样创建一个寄宿图形(CALyer
的contents
属性,如果要给contents赋值就是layer.contents = (__bridge id)image.CGImage
,所以占用内存大),所以无论有多大,都不会占用太多的内存。 - 不会被图层边界剪裁掉。一个
CAShapeLayer
可以在边界之外绘制。你的图层路径不会像在使用Core Graphics
的普通CALayer
一样被剪裁掉。 - 不会出现像素化。当你给
CAShapeLaye
r做3D变换时,它不像一个有寄宿图的普通图层一样变得像素化。
到此,运行我们就可以看到效果了,如下