Swift4、一回転のアニメーション

謎のプリン語る。
プログラミングの役立つ情報とか、どうでもいい雑談とか書いてます。
一人書く人増えました。

Swift4、一回転のアニメーション

みやびプリン 500 316

500 320

Swift4、一回転のアニメーション - サムネイル

※この記事は6年以上前の記事です。
現在は状況が異なる可能性がありますのでご注意ください。

どうも、ずいぶんごぶさたです。

ここ最近、またSwiftやらせてもらってます。
しかも、上司から正式に、やってみて、言うわれてやっております。
でも本職やりながらですけどねw

さて、表記の件いってみようか。
ローディングのスピナー作る時とかよくやるよね。
だいたいは、下記の方法が出てくるだろう。

import UIKit

// ひとまず画面サイズをとっとく
let screenSize: CGSize = CGSize(width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height)

class ViewController: UIViewController {
  // ひとまず回転画像インスタンスを定義
  let loadingImage: UIImageView = UIImageView(image: UIImage(named: "loading_circle"))
  
  override func viewDidLoad() {
    super.viewDidLoad()
    
    setUpLoading()
  }

  func setUpLoading(){
    // ローディング画像の設定
    self.loadingImage.frame = CGRect(x: (screenSize.width - self.loadingImage.frame.size.width) / 2, y: (screenSize.height - self.loadingImage.frame.size.height) / 2, width: self.loadingImage.frame.size.width, height: self.loadingImage.frame.size.height)
    
    self.view.addSubview(self.loadingImage)

    // UIViewのanimateメソッドを使ってやる
    UIView.animate(withDuration: 2.0, animations: {
      // アニメーションの最終状態
      self.loadingImage.transform = CGAffineTransform(rotationAngle: CGFloat(Double.pi))
    }, completion: ({ (openFlgIn) in
      // アニメーション完了時になんかする。引数には完了できたかのBool値が入ってる
    }))
  }
}

今は、便利だね。animateってメソッド、デフォであるもんね。
昔そんな便利なの無かったよ。

んで、お気づきの方は気づいただろうが、
実はこれだと半回転しかしないし、リピートもされない。
CGFloat(Double.pi)には円周率が入ってるんだけど、
これだと半回転なのだ。
だったら、単純に2倍すればいいんじゃね?思うけど、
それだと、一回転して元の回転量(0)と認識され、アニメーションは実行されない。
他のサイトのエントリだったら、こっからいろいろやるんだけど、
(現在のtransformの回転値をとってなんだかんだしたりする)
みやびは、めんどうなので、タイマーを使って、
セルフアニメーションを作った。
それが下記になる。

import UIKit

// ひとまず画面サイズをとっとく
let screenSize: CGSize = CGSize(width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height)

class ViewController: UIViewController {
  // ひとまず回転画像インスタンスを定義
  let loadingImage: UIImageView = UIImageView(image: UIImage(named: "loading_circle"))
  // タイマーと回転の変数を用意
  var animationTimer: Timer? = nil
  var rotate: CGFloat = 0
  // 一回転にかかる秒数
  let singleRotateTime: CGFloat = 4.0
  // 一回のタイマー操作で回転する量
  var singleRotateValue: CGFloat = 0
  // 円周率から、度数法でいう1度の時のラジアン(円周率)を求めておく
  let radSingle: CGFloat = CGFloat(Double.pi) / 180
  
  override func viewDidLoad() {
    super.viewDidLoad()
    
    setUpLoading()
  }

  func setUpLoading(){
    // ローディング画像の設定
    self.loadingImage.frame = CGRect(x: (screenSize.width - self.loadingImage.frame.size.width) / 2, y: (screenSize.height - self.loadingImage.frame.size.height) / 2, width: self.loadingImage.frame.size.width, height: self.loadingImage.frame.size.height)
    
    self.view.addSubview(self.loadingImage)

    // 一回のタイマー操作で回転する量を入れる
    self.singleRotateValue = CGFloat(Double.pi) * 2 / self.singleRotateTime / 30
    // ↑円周率 × 2(一回転の量) ÷ 一回転の秒数(これで一回転の時の量) / 30フレーム(タイマー一回分の回転量)

    // Timerメソッドを使ってやる
    self.animationTimer = Timer.scheduledTimer(withTimeInterval: TimeInterval(0.033333333), repeats: true, block: {(Timer) in
      // 現在の回転量から、一回分を足す
      self.rotate += self.singleRotateValue
      // 度数法の時何度か
      let chkAngle = self.rotate / self.radSingle
      // 360度以上(0度超えた)だったら、0に戻す
      if chkAngle >= 360 {
        self.rotate = 0
      }
      // Transformで、回転かける
      self.loadingImage.transform = CGAffineTransform(rotationAngle: self.rotate)
    })
  }
}

これで、回転する画像ができたってわけだ。
回転を終えたければ、self.animationTimer.inalidate()を実行すればいい。
(ただし、一回これを実行すると、Timerを再定義しなければいけない)

Swiftは敷居が低めになっているとはいえ、オブジェクト指向なので、
やっぱり難しいです。
制約も多いし(制約と聞くとクラピカとゴンが目に浮かんだ)
でも、やってく中でいろいろ見つけてるので、また記事あげたいと思います。
(今回、えらいあっさり終えれた)

ではまた。

トラックバック(0)

トラックバックURL:

コメントする

ページトップへ戻る