偶然間在網頁上看到一個過山車動畫覺得很炫,就想用
swift
純代碼實現了一個類似的效果,因為沒有設計天賦,所以就完全高仿的人家的效果-.-下面上效果圖:
給大家介紹一下項目中主要會用到的類:
CAShapeLayer
CAGradientLayer
CAKeyframeAnimation
實現的主要思路
漸變的背景用CAGradientLayer
實現,其他例如山峰,草坪和軌道可以用CAShapeLayer
配合UIBezierPath
實現,然后云朵,樹木和大地直接用CALayer
通過設置contents
實現,然后云朵和過山車的動畫實現用CAKeyframeAnimation
,這樣分析其實做一個這樣的動態效果并不是很難,下面就是實現過程和簡單的代碼示例。下載demo有完整代碼
CAGradientLayer
CAGradientLayer
是用來生成兩種或更多顏色平滑漸變的。相比于Core Graphics
來說CAGradientLayer
的真正好處在于繪制使用了硬件加速。這說明通過CAGradientLayer
來繪制漸變的效果比用Core Graphics
的效率更高。我們通過CAGradientLayer
來實現這個項目中的背景下載demo有完整代碼:
//初始化背景
func initGradientLayer(size:CGSize) -> CAGradientLayer {
let layer:CAGradientLayer = CAGradientLayer()
layer.frame = CGRect(x: 0, y: 0, width: size.width, height: size.height - 20)
//設置漸變的顏色
layer.colors = [UIColor.init(colorLiteralRed: 178.0/255.0, green: 226.0/255.0, blue: 248.0/255.0, alpha: 1.0).CGColor, UIColor.init(colorLiteralRed: 232.0/255.0, green: 244.0/255.0, blue: 193.0/255.0, alpha: 1.0).CGColor]
//設置漸變的方向為從左上到右下
layer.startPoint = CGPoint(x: 0, y: 0)
layer.endPoint = CGPoint(x: 1, y: 1)
view.layer.addSublayer(layer)
return layer
}
CAShapeLayer
CAShapeLayer
是一個通過矢量圖形而不是bitmap
來繪制的圖層子類。你指定諸如顏色和線寬等屬性,用CGPath
來定義想要繪制的圖形,最后CAShapeLayer就自動渲染出來了。當然,你也可以用Core Graphics
直接向原始的CALyer的內容中繪制一個路徑,相比直下,使用CAShapeLayer
有以下一些優點:
- 渲染快速。
CAShapeLayer
使用了硬件加速,繪制同一圖形會比用Core Graphics
快很多。
- 高效使用內存。一個
CAShapeLayer
不需要像普通CALayer
一樣創建一個寄宿圖形,所以無論有多大,都不會占用太多的內存。
- 不會被圖層邊界剪裁掉。一個
CAShapeLayer
可以在邊界之外繪制。你的圖層路徑不會像在使用Core Graphics
的普通CALayer
一樣被剪裁掉(如我們在第二章所見)。
- 不會出現像素化。當你給
CAShapeLayer
做3D
變換時,它不像一個有寄宿圖的普通圖層一樣變得像素化。
我們用CAShapeLayer
來繪制草地,山坡和過山車的軌道,下面給大家通過繪制草坪的代碼簡單介紹一下用法下載demo有完整代碼:
//初始化草坪
func initGrasslandlayer(size:CGSize) -> CAShapeLayer {
let grasslandOne = CAShapeLayer()
//通過UIBezierPath來繪制路徑
let pathOne:UIBezierPath = UIBezierPath()
pathOne.moveToPoint(CGPoint(x: 0, y: size.height - 20))
pathOne.addLineToPoint(CGPoint(x: 0, y: size.height - 100))
pathOne.addQuadCurveToPoint(CGPoint(x: size.width/3.0, y: size.height - 20), controlPoint: CGPoint(x: size.width/6.0, y: size.height - 100))
grasslandOne.path = pathOne.CGPath
//設置草坪的顏色
grasslandOne.fillColor = UIColor.init(colorLiteralRed: 82.0/255.0, green: 177.0/255.0, blue: 44.0/255.0, alpha: 1.0).CGColor
view.layer.addSublayer(grasslandOne)
}
CAKeyframeAnimation
CAKeyframeAnimation
類為對象提供了關鍵幀動畫的功能。你創建一個CAKeyframeAnimation
對象使用animationWithKeyPath:
指定屬性的關鍵路徑,你可以指定要使用關鍵幀的值來控制時間和動畫的行為。我們可以通過CAKeyframeAnimation
來實現過山車在軌道上的的動畫和云朵的動畫,下面是一小段示例代碼下載demo有完整代碼:
//添加綠色軌道的動畫
func addGreenCarPathAnimation(size:CGSize) {
let carLayer:CALayer = CALayer()
carLayer.frame = CGRect(x: 0, y: 0, width: 17, height: 11)
carLayer.contents = UIImage.init(named: "otherCar")!.CGImage
//繪制路徑
let path:UIBezierPath = UIBezierPath()
path.lineCapStyle = .Round
path.lineJoinStyle = .Round
path.moveToPoint(CGPoint(x: size.width + 10, y: size.height - 7))
path.addLineToPoint(CGPoint(x: size.width + 10, y: size.height - 77))
path.addQuadCurveToPoint(CGPoint(x: size.width/1.8, y: size.height - 77), controlPoint: CGPoint(x: size.width - 120, y: 193))
path.addArcWithCenter(CGPoint(x: size.width/1.9, y: size.height - 140), radius: 63, startAngle: CGFloat(0.5*M_PI), endAngle: CGFloat(2.5*M_PI), clockwise: true)
path.addCurveToPoint(CGPoint(x: 0, y: size.height - 107), controlPoint1: CGPoint(x: size.width/1.8 - 60, y: size.height - 67), controlPoint2: CGPoint(x: 150, y: size.height/2.3-7))
path.addLineToPoint(CGPoint(x: -100, y: size.height + 7))
//關鍵幀動畫作用于position
let animation:CAKeyframeAnimation = CAKeyframeAnimation.init(keyPath: "position")
animation.path = path.CGPath
//動畫節奏為線性動畫
animation.timingFunction = CAMediaTimingFunction.init(name: kCAMediaTimingFunctionLinear)
//動畫時間
animation.duration = 6
//動畫重復次數
animation.repeatCount = MAXFLOAT
//動畫是否逆轉
animation.autoreverses = false
animation.calculationMode = kCAAnimationCubicPaced
//動畫角度是否調整
animation.rotationMode = kCAAnimationRotateAuto
view.layer.addSublayer(carLayer)
carLayer.addAnimation(animation, forKey: "carAnimation")
}
上面的代碼只是簡單的示例,完整代碼得去我的github上去下載,到這里也就基本上完成了,大家有什么疑問可以留言評論,謝謝大家的觀看