CGPointをUIView座標系からCALayer座標系に変換します
-
03-07-2019 - |
質問
あるCGPointをあるUIViewから別のUIViewへ、そしてあるCALayerから別のCALayerへ転送する方法があります。 CGPointをUIViewの座標系からCALayerの座標系に変更する方法が見つかりません。
レイヤーとそのホストビューの座標系は同じですか?それらの間でポイントを変換する必要がありますか?
ありがとう、 コーリー
[編集]
答えてくれてありがとう! iPhoneとMacのCAの違い/類似点に関する情報を見つけるのは困難です。 Appleのドキュメントでこの問題を直接解決できなかったことに驚きました。
トラブルシューティングを行っているバグを解決するためにこの回答を追求していましたが、これまでのところ最善の推測でしたが、間違ったツリーを探していると思われます。座標系が同じ場合、別の問題があります...
私が抱えている実際の問題は、スタックオーバーフローにあります。 レイヤーヒットテストのみレイヤーの下半分に触れたときにレイヤーを返す
解決
座標系を反転したい場合、CALayersの transform
プロパティを適切な変換に設定できますが、これはおそらく contents
の描画を反転することに注意してください同様に(私はそれをテストしていませんが、これは真実であるということは理にかなっています)。 UIViewに関連付けられたCALayerが同じ座標系を共有しているという私の主張は、実際には完全に間違っている可能性があります。 CALayersはUIViewsと同じ座標系を使用することもあります(つまり、垂直に反転することはありません)が、CoreGraphicsはUIKitに対して反転した座標系を使用するためだと思いました。
テストする簡単な方法は、画面サイズのCALayerをビューのレイヤーのサブレイヤーとして追加してから、別の小さなCALayerをそのサブレイヤーとして追加することです。 (0、0、320、100)に表示されるように設定し、iPhoneの画面の上部または下部に表示されるかどうかを確認できます。これにより、CoreAnimationのY軸の方向がわかります。
- (void)viewDidLoad {
[super viewDidLoad];
CALayer *rootLayer = [CALayer layer];
rootLayer.frame = self.view.layer.bounds;
CALayer *smallLayer = [CALayer layer];
smallLayer.frame = CGRectMake(0, 0, rootLayer.bounds.size.width, 50);
smallLayer.backgroundColor = [UIColor blueColor].CGColor;
[rootLayer addSublayer:smallLayer];
[self.view.layer addSublayer:rootLayer];
}
このテストを自分で実行したところ、CALayersは実際にUIViewsと同じ座標系を使用しているように見えるため、CALayerがY軸を反転するという私の主張は間違いです。ただし、CoreGraphicsで直接描画する場合、CoreGraphicsは反転したY軸を使用することに注意してください(ただし、UIViewサブクラスまたはCALayerデリゲートで描画する場合、CoreGraphicsコンテキストは既にUIView(またはCALayer)の座標系に一致するように反転しました。
したがって、これまでに作成した短い答えは、CALayerの座標系が対応するUIViewの座標系と一致する必要があるということです。
他のヒント
hitTestのドキュメントによると:
/* Returns the farthest descendant of the layer containing point 'p'.
* Siblings are searched in top-to-bottom order. 'p' is in the
* coordinate system of the receiver's superlayer. */
だからあなたはする必要があります(このような何か):
CGPoint thePoint = [touch locationInView:self];
thePoint = [self.layer convertPoint:thePoint toLayer:self.layer.superlayer];
CALayer *theLayer = [self.layer hitTest:thePoint];
Appleのドキュメントに関しては、「iPhone OS Note」を見つけました。 Core Animation Programming Guide (2008-11-13)。
UIViewインスタンスのデフォルトのルートレイヤーは、UIViewインスタンスのデフォルトの座標系と一致する反転座標系を使用します。原点は左上にあり、値は上下に増加します。 CALayerをインスタンス化して作成されたレイヤーは、標準のCore Animation座標系を直接使用します。
私のテストから、サブレイヤーは親レイヤーと同じ座標系を共有しているため、サブレイヤーをUIViewレイヤーに追加する場合、同じ座標系を共有することがわかりました。
座標系を反転させて、原点が左上隅になるようにする場合は、y軸を反転させるこの変換を使用する必要があります。 (x、y、1)=(x '、y'、1)* [1 0 0]、[0 -1 0]、[0 heigth 1]
コードに変換されるは次のとおりです。 [your_layer setAffineTransform:CGAffineTransformMake(1,0,0、-1,0、heigth)];
UIViewとそれに関連するレイヤーの座標系は同じでなければなりません。ただし、自分でレイヤーを作成する場合、座標系は垂直に反転します。
Methods that fixing frames and points
- (CGRect) fixRect:(CGRect)rect inRect:(CGRect)container
{
CGRect frame = rect;
frame.origin.y = container.size.height - frame.origin.y - frame.size.height;
return frame;
}
- (CGPoint) fixPoint:(CGPoint)point fromPoint:(CGSize)containerSize
{
CGPoint frame = point;
frame.y = size.height - frame.y;
return frame;
}
この2つは同じ座標系を持っていると思います。