LoginSignup
83
83

More than 5 years have passed since last update.

[Objective-C] UIViewの座標と座標変換について

Last updated at Posted at 2014-02-13

UIViewはそれぞれ座標系を保持しています。
自身のView座標系の値はview.bounds、親ビューからの相対位置はview.frameが保持しています。
言葉だと分かりづらいので、図にすると以下のような値をそれぞれ保持していることになります。
(cview1、cview2ともにUIView)

cap.png

実際に上記の状態で以下のログを出力してみます。

//cview1のframeとboundsを出力
NSLog(@"cview1.frame : %@", NSStringFromCGRect(self.cview1.frame));
NSLog(@"cview1.bounds: %@", NSStringFromCGRect(self.cview1.bounds));

//cview2のframeとboundsを出力
NSLog(@"cview2.frame : %@", NSStringFromCGRect(self.cview2.frame));
NSLog(@"cview2.bounds: %@", NSStringFromCGRect(self.cview2.bounds));
cview1.frame : {{0, 0},   {320, 240}}
cview1.bounds: {{0, 0},   {320, 240}}
cview2.frame : {{0, 240}, {320, 240}}
cview2.bounds: {{0, 0},   {320, 240}}

ログを見ると一目瞭然ですね。
frame.originは親ビューからの相対位置が保持されているのに対し、bounds.originは自身の座標系になっているのが分かります。

以上を踏まえた上で。
とある位置(例えばタッチされた位置など)が与えられたとして、それぞれの座標系ではどの位置なのかというのを取得したい場合があります。
そのときに使うのが、UIViewのインスタンスメソッドconvertPoint:toViewconvertPoint:fromViewというメソッドになります。

これはそれぞれレシーバ(※)から対象(あるいはその逆)の座標変換を行うメソッドです。
簡単なテストをしてみましょう。以下のように指定し、ログに出力してみます。

※…上記メソッドを実行しているインスタンス

convertPoint:fromView:サンプル

//touchオブジェクトを取得
UITouch *touch = [touches anyObject];

//タッチ位置が、該当のView上のどこかを取得
CGPoint touchpoint1 = [touch locationInView:self.cview1];

//cview1からcview2の座標系に位置を変換
CGPoint touchpoint2 = [self.cview2 convertPoint:touchpoint1 fromView:self.cview1];

NSLog(@"touchpoint1: %@", NSStringFromCGPoint(touchpoint1));
NSLog(@"touchpoint2: %@", NSStringFromCGPoint(touchpoint2));
touchpoint1: {93.5, 184.0}
touchpoint2: {93.5, -56.0}

サンプルでは、touchesBegan:withEvent:メソッドで得られたタッチ位置を元に、self.cview1self.cview2のそれぞれの座標系での位置を出力しています。

3D系に詳しい人であれば、 ワールド座標系とモデル座標系の座標変換をイメージ すると分かりやすいと思います。

convert***系メソッド

上記のメソッドにはいくつか類似のメソッドがあります。

メソッド 説明
convertRect:toView: CGRect レシーバの座標系をtoView座標系に変換
convertRect:fromView: CGRect fromView座標系をレシーバの座標系に変換
convertPoint:toView: CGPoint レシーバの座標系をtoView座標系に変換
convertPoint:fromView: CGPoint fromView座標系をレシーバの座標系に変換

上記メソッド、なにをどう変換するかをしっかり把握しておくことが大事です。

// aView座標系の座標`aView.bounds`を、`toView`座標系に変換
[aView convertRect:aView.bounds toView:otherView];

上記ポイントは、aView.boundsを変換している点です。これをaView.frameにすると違った結果になってしまうので注意が必要です。

83
83
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
83
83