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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Xcode 7

Xcode 7は、ソフトウェア開発のためのアップルの統合開発環境であるXcodeのバージョン。UIを作成するために用いるグラフィカルツールです。iOS9/OS X El Capitan/watchOS2に対応。Swift 2コンパイラーが搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

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

Swift 2

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

Q&A

解決済

1回答

2276閲覧

Swiftで角度をつけた画像をドラッグすると画像が消える

keys

総合スコア215

Xcode 7

Xcode 7は、ソフトウェア開発のためのアップルの統合開発環境であるXcodeのバージョン。UIを作成するために用いるグラフィカルツールです。iOS9/OS X El Capitan/watchOS2に対応。Swift 2コンパイラーが搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

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

Swift 2

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

0グッド

0クリップ

投稿2017/05/28 12:32

イメージ説明

説明

UIImageで画像を生成します。CGAffineTransformを使い画像の角度を変えて回転を加えます。touchesMovedメソッドを使って画像をつまんで動かせる(ドラッグ)できるようにしたいです。

状況

初期の状態ではヒトカゲの画像はデバイスの中心に描画されるように実装がしてあり、この状態では画像は問題なくつまんで動かす(ドラッグ)させることができます。

下記のgifでは、画面下のボタンを押すとCGAffineTransformの処理が動いてランダムな角度で画像が回転するようになっていますが、画像に角度を与え回転させた状態で画像を動かしてみれば、gif画像にあるように、だんだん細くなって最後には消滅します。

全ソース

swift

1 2import UIKit 3 4class ViewController: UIViewController { 5 6 let HitokageImage = UIImageView() 7 8 override func viewDidLoad() { 9 super.viewDidLoad() 10 11 let screenWidth:CGFloat = view.frame.size.width 12 let screenHeight:CGFloat = view.frame.size.height 13 14 HitokageImage.image = UIImage(named: "hitokage") 15 HitokageImage.frame = CGRect(x:0, y:0, width:250, height:250) 16 HitokageImage.center = CGPoint(x:screenWidth/2, y:screenHeight/2) 17 HitokageImage.isUserInteractionEnabled = true 18 self.view.addSubview(HitokageImage) 19 } 20 21 override func didReceiveMemoryWarning() { 22 super.didReceiveMemoryWarning() 23 // Dispose of any resources that can be recreated. 24 } 25 26 // ドラッグ 27 override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) { 28 29 let touchEvent = touches.first! 30 let preDx = touchEvent.previousLocation(in: self.view).x 31 let preDy = touchEvent.previousLocation(in: self.view).y 32 let newDx = touchEvent.location(in: self.view).x 33 let newDy = touchEvent.location(in: self.view).y 34 let dx = newDx - preDx 35 let dy = newDy - preDy 36 var viewFrame: CGRect = HitokageImage.frame 37 viewFrame.origin.x += dx 38 viewFrame.origin.y += dy 39 HitokageImage.frame = viewFrame 40 self.view.addSubview(HitokageImage) 41 42 } 43 44 @IBAction func HitokageRotation(_ sender: Any) { 45 46 let random = arc4random_uniform(360) 47 48 HitokageImage.transform = CGAffineTransform(rotationAngle: CGFloat( random ) ) 49 50 } 51}

実装部分

画像に角度を与えている場所

let random = arc4random_uniform(360) HitokageImage.transform = CGAffineTransform(rotationAngle: CGFloat( random ) )

画像のタッチイベントを許可

swift

1 2 HitokageImage.isUserInteractionEnabled = true 3 4

ドラッグ処理

swift

1 2 説明 3 4UIImageで画像を生成します。CGAffineTransformを使い画像の角度を変えて回転を加えます。touchesMovedメソッドを使って画像をつまんで動かせる(ドラッグ)できるようにしたいです。 5 6 状況 7 8初期の状態ではヒトカゲの画像はデバイスの中心に描画されるように実装がしてあり、この状態では画像は問題なくつまんで動かす(ドラッグ)させることができます。 9 10下記のgifでは、画面下のボタンを押すとCGAffineTransformの処理が動いてランダムな角度で画像が回転するようになっていますが、画像に角度を与え回転させた状態で画像を動かしてみれば、gif画像にあるように、だんだん細くなって最後には消滅します。 11 12 全ソース 13 14import UIKit 15 16class ViewController: UIViewController { 17 18 let HitokageImage = UIImageView() 19 20 override func viewDidLoad() { 21 super.viewDidLoad() 22 23 let screenWidth:CGFloat = view.frame.size.width 24 let screenHeight:CGFloat = view.frame.size.height 25 26 HitokageImage.image = UIImage(named: "hitokage") 27 HitokageImage.frame = CGRect(x:0, y:0, width:250, height:250) 28 HitokageImage.center = CGPoint(x:screenWidth/2, y:screenHeight/2) 29 HitokageImage.isUserInteractionEnabled = true 30 self.view.addSubview(HitokageImage) 31 } 32 33 override func didReceiveMemoryWarning() { 34 super.didReceiveMemoryWarning() 35 // Dispose of any resources that can be recreated. 36 } 37 38 // ドラッグ 39 override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) { 40 41 let touchEvent = touches.first! 42 let preDx = touchEvent.previousLocation(in: self.view).x 43 let preDy = touchEvent.previousLocation(in: self.view).y 44 let newDx = touchEvent.location(in: self.view).x 45 let newDy = touchEvent.location(in: self.view).y 46 let dx = newDx - preDx 47 let dy = newDy - preDy 48 var viewFrame: CGRect = HitokageImage.frame 49 viewFrame.origin.x += dx 50 viewFrame.origin.y += dy 51 HitokageImage.frame = viewFrame 52 self.view.addSubview(HitokageImage) 53 54 } 55

試したこと

角度を与えるまでは正常に動かすことができて、角度を与えた瞬間にバグるっていうことは、角度を与えている場所が問題になってるってこと。 CGAffineTransform で画像を回転させるのではなく、角度を変えた画像をアドサブビューする形にしてみても同じことがおこる。

なぜ、角度を変えると急にこうなってしまうのかわからない。横に細く伸びながら消えていくっていうことは、横幅が以上に伸びまくってるっていうことでしょうか画像をドラッグする時、ドラッグが感知できる画像がまっすぐの画像だけだから、斜めとかにしてると、おかしくなるのでしょうか。

謎です!

お力お貸しください。

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

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

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

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

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

guest

回答1

0

ベストアンサー

リファレンスに気になる警告がありました。transformを操作している場合、frameはむやみにいじらない方がよさそうです。代わりに、centerで位置を設定してみてはいかがでしょうか。

参考:frame - UIView | Apple Developer Documentation

[追記]
該当部分の抜粋が推奨されるとのことで、リファレンスの引用を追記します。

Warning
If the transform property is not the identity transform, the value of this property is undefined and therefore should be ignored.

※transformプロパティが恒等変換でない場合(要するに何らかの移動・回転・伸縮・剪断が行われている場合)、このプロパティの値は未定義であるので、無視するべきである...のような意味でしょうか。

Changes to this property can be animated. However, if the transform property contains a non-identity transform, the value of the frame property is undefined and should not be modified. In that case, you can reposition the view using the center property and adjust the size using the bounds property instead.

※このプロパティへの変更はアニメートできる(つまりアニメーション系メソッドなどでframeを書き換えてのアニメーションが可能)。しかし、transformが非恒等変換である場合、frameプロパティの値は未定義であり変更すべきでない。そのようなケースでは、代わりにビューのcenterプロパティで移動、boundsプロパティでサイズ調整できる...のような意味でしょうか。

投稿2017/05/28 14:44

編集2017/05/28 22:06
Bongo

総合スコア10807

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

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

fuzzball

2017/05/29 01:52 編集

この辺参考になるかも。 http://qiita.com/naodroid/items/fdcb956221a82cc8480a あと、角度はラジアンで指定しますので、 HitokageImage.transform = CGAffineTransform(rotationAngle: CGFloat(Double(random) * Double.pi / 180)) //radian = degree * π / 180 こんな感じです。(型エラー出たらキャスト修正して下さい)
Bongo

2017/05/29 01:48

おお、最後の方に今回のケースと関係しそうな現象に言及されていますね。情報ありがとうございます。
keys

2017/05/29 03:01

> 自分がこういうコードを書いて実験したときは、frame操作のたびにboundsがゆがみ、最後にはboundsの高さが0になり見えなくなりました。 まさしく全く同じ現象です。参考にさせていただきます。今やってる感じでは、例えば90度や180度などの安易な角度であれば、円周率からラジアンを算出して、角度をつけた状態でも動かせましたが、75度とかになると、frame操作のたびにboundsがゆがみ、最後にはboundsの高さが0になり見えなくなりますね。
keys

2017/05/29 03:09 編集

``` HitokageImage.transform = CGAffineTransform(rotationAngle: CGFloat( M_PI_2 ) ) ``` 上記のように、正確にラジアンを指定できれば、角度をつけた状態でも動かせます。` M_PI_2 ` は90度のように。
ozwk

2017/05/29 03:12

正確云々は今回の話多分関係ないと思いますが一応: 180度 <-> piなので x度 <-> x*pi/180です。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問