質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Swift 2

Swift 2は、Apple社が独自に開発を行っている言語「Swift」のアップグレード版です。iOSやOS X、さらにLinuxにも対応可能です。また、throws-catchベースのエラーハンドリングが追加されています。

Q&A

解決済

2回答

1901閲覧

[Swift]NSTimerを使ったアニメーションのコマ落ち対策

k.has

総合スコア34

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Swift 2

Swift 2は、Apple社が独自に開発を行っている言語「Swift」のアップグレード版です。iOSやOS X、さらにLinuxにも対応可能です。また、throws-catchベースのエラーハンドリングが追加されています。

0グッド

0クリップ

投稿2016/12/20 22:13

編集2016/12/20 22:17

2秒間でImageVeiwが画面外から画面中央に一定の速度で移動するアニメーション(NSTimer使用)を使って実装中です。※効果音やその他のアニメーションとの関係で2秒ちょうどで移動が完了するようにしたいと思っています。

イメージ説明

Androidの実装時に繰り返す描画の経過時間に応じてイメージの座標が変わるようにしてコマ落ちの対策をしていたのですが、Swiftの場合はコマ落ちの対策はするのが一般的なのでしょうか?

ちなみに、他のアニメーション含め、多くのイメージを一度に動かすようなことはないので、アプリ単体を動かしただけではコマ落ちすることはほぼないので考えなくてもいいのかもしれないのですが、ググってもコマ落ちでヒットしなかったので。

ちなみに以下のような感じで実装すると思ったように動きますが、なんか滑らかに動きません。この時間に応じて、ということを考えずに実装するともっとシンプルになって、かつ滑らかに動きます…汗

Swift

1class AnimationB: UIViewController{ 2 3 var time: CGFloat! 4 var startTime: Double! 5 var imageView: UIImageView! //UIImageの設定等省略 6 var imageH: CGFloat! //イメージの高さ 7 var xPosition,yPosition: CGFloat! //イメージ座標 8 9 func startAnimation(){ 10 startTime = CFAbsoluteTimeGetCurrent() 11 time = CGFloat(CFAbsoluteTimeGetCurrent()) 12 13 timer = NSTimer.scheduledTimerWithTimeInterval( 14 0.017, //FPS:60 15 target: self, 16 selector: #selector(AnimationB.animation), 17 userInfo: nil, 18 repeats: true) 19 } 20 21 @objc func animation(){ 22 let nowTime = CFAbsoluteTimeGetCurrent() 23 24 if nowTime - startTime < 2 { 25 let passTime = CGFloat(CFAbsoluteTimeGetCurrent()) - time 26 yPosition = yPosition - (imageH * 1.2) / 2 * passTime 27 imageView.center = CGPoint(x: xPosition, y: yPosition) 28 time = CGFloat(CFAbsoluteTimeGetCurrent()) 29 }else{ 30 timer.invalidate() 31 } 32 33 } 34 35 override func viewDidLoad() { 36 super.viewDidLoad() 37 } 38 39 override func didReceiveMemoryWarning() { 40 super.didReceiveMemoryWarning() 41 } 42 43}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

NSTimerを使用するのではなくてアニメーションさせるのはいかがでしょうか?
※ 移動時間、遅延時間、アニメーションの速さ等の調整(options)、終了後の処理などが設定できます。

swift

1func animation() { 2 3 UIView.animate(withDuration: 2.0, delay: 0, options: UIViewAnimationOptions.curveLinear, animations: { 4 5 // imageViewの最終的な位置を設定 6 self.imageView.center = self.view.center 7 8 }, completion: { finished in 9 // アニメーションが終了時に実行したいことを記述 10 11 }) 12}

投稿2016/12/20 22:31

編集2016/12/20 22:44
_Kentarou

総合スコア8490

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

k.has

2016/12/24 22:51

_Kentaoruさん 思い通りに動きました!ありがとうございます。 そして断然こっちの方がシンプルですね(^^;
guest

0

正しい解決方法は**_Kentarou**さんの回答を見ていただくとして、質問に書かれているような方法でやる場合のアドバイスを書きたいと思います。

一定時間毎に移動量を加算(減算)していますが、これだと誤差が蓄積される可能性がありますので、経過時間から直接座標を求めた方が良いと思います。

swift

1func animation() { 2 let nowTime = CFAbsoluteTimeGetCurrent() 3 4 let src = self.view.frame.height + imageH/2 //始点=画面下 5 let dst = self.view.frame.height/2 //終点=画面中央 6 let duration = 2.0 //アニメション時間 7 //※この3つは毎回ここで設定する必要はありません 8 9 if nowTime - startTime < duration { 10 //経過時間から座標を求める 11 yPosition = src + (dst - src) * CGFloat((nowTime - startTime) / duration) 12 } else { 13 //終了時は終点の座標を設定しないとズレる場合があります 14 yPosition = dst 15 timer.invalidate() 16 } 17 imageView.center = CGPoint(x: xPosition, y: yPosition) 18 //print("nowTime=", nowTime, "y=", imageView.center.y) 19}

あと、Androidでも出来るみたいですよ。
Androidアプリ開発におけるTweenアニメーション

投稿2016/12/21 00:30

fuzzball

総合スコア16731

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

k.has

2016/12/24 22:50

fuzzballさん なーーーるほど!本当ですね・・・。 とても勉強になりますm(._.)m Androidのことも教えていただきありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問