コードはこんな感じです。
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】円形にゲージが増えるアニメーション

