WEBOPIXEL

iOS+Swiftでカウントダウンアニメーション

Posted: 2015.03.28 / Category: iOS / Tag: 

ゲームを始まる前とかに使えそうな3,2,1スタート的なアニメーションのやつです。

Sponsored Link

コードはこんな感じです。

import UIKit

class StartCountDownControllerView: UIViewController  {
	
	var _countNumberLabel:UILabel!
	let _countDownMax:Int = 3
	var _countDownNum:Int = 3
	var _circleView:UIView!
	
	override func viewDidLoad() {

		// カウントダウン数値ラベル設定
		_countNumberLabel = UILabel(frame: CGRectMake(0, 0, self.view.frame.width, self.view.frame.height))
		_countNumberLabel.font = UIFont(name: "HelveticaNeue", size: 54)
		// 中心揃え
		_countNumberLabel.textAlignment = NSTextAlignment.Center
		_countNumberLabel.baselineAdjustment = UIBaselineAdjustment.AlignCenters
		self.view.addSubview(_countNumberLabel)

		_circleView = UIView(frame : CGRectMake((self.view.frame.width/2)-100, (self.view.frame.height/2)-100, 200, 200))
		_circleView.layer.addSublayer(drawCircle(_circleView.frame.width, strokeColor: UIColor(red:0.0,green:0.0,blue:0.0,alpha:0.2)))
		_circleView.layer.addSublayer(drawCircle(_circleView.frame.width, strokeColor: UIColor(red:0.0,green:0.0,blue:0.0,alpha:1.0)))
		self.view.addSubview(_circleView)
	}
	
	// 遷移毎に実行
	override func viewWillAppear(animated: Bool) {
		// 数値をリセット
		_countDownNum = _countDownMax
		_countNumberLabel.text = String(_countDownNum)
		// アニメーション開始
		circleAnimation(_circleView.layer.sublayers[1] as CAShapeLayer)
	}
	
	func drawCircle(viewWidth:CGFloat, strokeColor:UIColor) -> CAShapeLayer {
		var circle:CAShapeLayer = CAShapeLayer()
		// ゲージ幅
		let lineWidth: CGFloat = 20
		// 描画領域のwidth
		let viewScale: CGFloat = viewWidth
		// 円のサイズ
		let radius: CGFloat = viewScale - lineWidth
		// 円の描画path設定
		circle.path = UIBezierPath(roundedRect: CGRectMake(0, 0, radius, radius), cornerRadius: radius / 2).CGPath
		// 円のポジション設定
		circle.position = CGPointMake(lineWidth / 2, lineWidth / 2)
		// 塗りの色を設定
		circle.fillColor = UIColor.clearColor().CGColor
		// 線の色を設定
		circle.strokeColor = strokeColor.CGColor
		// 線の幅を設定
		circle.lineWidth = lineWidth
		return circle	}
	
	func circleAnimation(layer:CAShapeLayer) {
		// アニメーションkeyを設定
		var drawAnimation = CABasicAnimation(keyPath: "strokeEnd")
		// callbackで使用
		drawAnimation.setValue(layer, forKey:"animationLayer")
		// callbackを使用する場合
		drawAnimation!.delegate = self
		// アニメーション間隔の指定
		drawAnimation!.duration = 1.0
		// 繰り返し回数の指定
		drawAnimation!.repeatCount = 1.0
		// 起点と目標点の変化比率を設定 (0.0 〜 1.0)
		drawAnimation!.fromValue = 0.0
		drawAnimation!.toValue = 1.0
		// イージング設定
		drawAnimation!.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)

		layer.addAnimation(drawAnimation, forKey: "circleAnimation")
	}
	
	override func animationDidStop(anim: CAAnimation!, finished flag: Bool) {
		let layer:CAShapeLayer = anim.valueForKey("animationLayer") as CAShapeLayer
		_countDownNum--
		// 表示ラベルの更新
		_countNumberLabel.text = String(_countDownNum)
		
		if _countDownNum <= 0 {
			//次の画面へ遷移(navigationControllerの場合)
			//let nextViewController:ViewController = ViewController()
			//self.navigationController?.pushViewController(nextViewController, animated: false)
			
		} else {
			circleAnimation(layer)
		}
	}
	
}
    

動作環境: Xcode 6.2

一応動くとは思うのですが、色々だめなところがある気がします。

メモ

  • 「CABasicAnimation」に「setValue(layer, forKey:~)」しておくと、アニメーション終了(animationDidStop)後、「valueForKey(~)」でレイヤーを取り出す。
  • 「_circleView.layer.sublayers[~]」で「addSublayer」で追加したレイヤーを取り出す。

円のアニメーション自体はこちらを使用させて頂きました。

【Swift】円形にゲージが増えるアニメーション