iOS動畫進階 - CAKeyframeAnimation實現過山車動畫

如果移動端訪問不佳,可以訪問我的個人博客

偶然間在網頁上看到一個過山車動畫覺得很炫,就想用swift純代碼實現了一個類似的效果,因爲沒有設計天賦,所以就完全高仿的人家的效果-.-下面上效果圖:

wcl.gif

給大家介紹一下項目中主要會用到的類:

  • 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
    }

屏幕快照 2016-06-22 上午12.16.14.png

CAShapeLayer

CAShapeLayer是一個通過矢量圖形而不是bitmap來繪製的圖層子類。你指定諸如顏色和線寬等屬性,用CGPath來定義想要繪製的圖形,最後CAShapeLayer就自動渲染出來了。當然,你也可以用Core Graphics直接向原始的CALyer的內容中繪製一個路徑,相比直下,使用CAShapeLayer有以下一些優點:

  • 渲染快速。CAShapeLayer使用了硬件加速,繪製同一圖形會比用Core Graphics快很多。

  • 高效使用內存。一個CAShapeLayer不需要像普通CALayer一樣創建一個寄宿圖形,所以無論有多大,都不會佔用太多的內存。

  • 不會被圖層邊界剪裁掉。一個CAShapeLayer可以在邊界之外繪製。你的圖層路徑不會像在使用Core Graphics的普通CALayer一樣被剪裁掉(如我們在第二章所見)。

  • 不會出現像素化。當你給CAShapeLayer3D變換時,它不像一個有寄宿圖的普通圖層一樣變得像素化。

我們用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)
    }

屏幕快照 2016-06-22 上午12.28.53.png

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上去下載,到這裏也就基本上完成了,大家有什麼疑問可以留言評論,謝謝大家的觀看

demo地址

參考文檔(非常好的一篇關於介紹CALayer的中文翻譯文檔,學習必看)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章