这几天学习了Video Tutorial iOS Animation with Swift 后面的课程,有这样一个下拉刷新的页面很不错,如图:
主要的实现思路就是在tableview上面放置了一个RefreshView,并实现UIScrollViewDelegate,在下拉一定距离后RefreshView上画一个圆,小飞机转圈。主要记录一下这部分的代码:
let ovalShapeLayer: CAShapeLayer = CAShapeLayer()
let airplaneLayer: CALayer = CALayer()
主要是一个圆形的ShapeLayer和一个小飞机的Layer,在整个RefreshView的init方法中,画出圆和放置小飞机的图片:
ovalShapeLayer.strokeColor = UIColor.whiteColor().CGColor //画笔颜色
ovalShapeLayer.fillColor = UIColor.clearColor().CGColor //画出的闭合图形的填充颜色
ovalShapeLayer.lineWidth = 4.0 //画笔粗细
ovalShapeLayer.lineDashPattern = [2, 3] //虚线的样式,什么地方划线,什么地方线断了
let refreshRadius = frame.size.height / 2 * 0.8
//画圆,用UIBezierPath曲线
ovalShapeLayer.path = UIBezierPath(ovalInRect: CGRect(x: frame.size.width / 2 - refreshRadius, y: frame.size.height / 2 - refreshRadius, width: 2 * refreshRadius, height: 2 * refreshRadius)).CGPath
layer.addSublayer(ovalShapeLayer)
let airplaneImage = UIImage(named: "icon-plane")
airplaneLayer.opacity = 1.0
airplaneLayer.contents = airplaneImage?.CGImage
airplaneLayer.bounds = CGRect(x: 0.0, y: 0.0, width: (airplaneImage?.size.width)!, height: (airplaneImage?.size.height)!)
airplaneLayer.position = CGPoint(x: frame.size.width/2 + frame.size.height / 2 * 0.8, y: frame.size.height / 2)
layer.addSublayer(airplaneLayer)
特别的是,这里的圆是用贝塞尔曲线画的,用到ovalInRect来画一个圆。现在需要为这两个Layer加上动画效果:
let strokeStartAnimation = CABasicAnimation(keyPath: "strokeStart")
strokeStartAnimation.fromValue = -0.5
strokeStartAnimation.toValue = 1
let strokeEndAnimation = CABasicAnimation(keyPath: "strokeEnd")
strokeEndAnimation.fromValue = 0.0
strokeEndAnimation.toValue = 1.0
let strokeAnimationGroup = CAAnimationGroup()
strokeAnimationGroup.duration = 1.5
strokeAnimationGroup.repeatDuration = 5.0
strokeAnimationGroup.animations = [strokeStartAnimation,strokeEndAnimation]
ovalShapeLayer.addAnimation(strokeAnimationGroup, forKey: nil)
圆圈主要是定义一个group动画效果,添加两个basic动画,分别是圆圈起始和结束的位置,形成旋转的效果。
let flightAnimation = CAKeyframeAnimation(keyPath: "position")
flightAnimation.path = ovalShapeLayer.path
flightAnimation.calculationMode = kCAAnimationPaced
let airplaneOrientationAnimation = CABasicAnimation(keyPath: "transform.rotation")
airplaneOrientationAnimation.fromValue = 0
airplaneOrientationAnimation.toValue = 2 * M_PI
let flightAnimationGroup = CAAnimationGroup()
flightAnimationGroup.duration = 1.5
flightAnimationGroup.repeatDuration = 5.0
flightAnimationGroup.animations = [flightAnimation,airplaneOrientationAnimation]
airplaneLayer.addAnimation(flightAnimationGroup, forKey: nil)
飞机转圈的动画首先用到CAKeyframeAnimation (关键帧动画),与CABasicAnimation的区别是CABasicAnimation只能从一个数值 (fromValue)变到另一个数值 (toValue),而CAKeyframeAnimation会使用一个 NSArray保存这些数值,path属性这里规定了layer的运动路径(这里也就是之前画的那个圆)。之后再给飞机加一个旋转的动画,模拟飞机飞行的感觉。需要注意的是,旋转的有一个旋转的坐标系:
参照这个坐标系设置fromValue和toValue,之后为airplaneLayer添加动画,如图: