将一个CGPoint从UIView坐标系转换为CALayer坐标系

12
有方法可以将一个CGPoint从一个UIView传递到另一个UIView,也可以从一个CALayer传递到另一个CALayer。但我找不到一种方法来改变UIView坐标系到CALayer坐标系的CGPoint。
图层和它的宿主视图是否具有相同的坐标系?我需要在它们之间转换点吗?
谢谢, Corey
[编辑]
感谢回答!很难找到关于iPhone和Mac上CA的差异/相似之处的信息。我很惊讶在任何苹果文档中都找不到直接解决这个问题的方式。
我正在追求这个答案以帮助解决我正在研究的错误,但我想我可能走错了路。如果坐标系是相同的,那么我就有另一个问题...
我正在遇到的实际问题可以在Stack Overflow上找到: layer hit test only returning layer when bottom half of layer is touched
6个回答

15

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];

这很奇怪,因为self.layer实际上是一个根层,所以它不应该有superlayer。但它确实有效。谢谢! - Rizo

6
根据苹果文档,我在Core Animation Programming Guide (2008-11-13)的“图层坐标系”部分找到了一个“iPhone OS Note”。

UIView实例的默认根图层使用翻转的坐标系,与UIView实例的默认坐标系相匹配 - 原点在左上角,值向下和向右增加。直接实例化CALayer创建的图层使用标准的Core Animation坐标系。


4
如果您想翻转CALayers的坐标系统,则可以将其transform属性设置为适当的变换,但请注意,这可能会翻转其对contents的绘制(我尚未测试过,但这是有道理的)。我的断言UIView关联的CALayer共享相同的坐标系实际上可能完全错误。它也可能是CALayers与UIView使用相同的坐标系(即它们从不垂直翻转),但我认为它们是因为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实际上使用与UIView相同的坐标系统,所以我声称CALayer翻转Y轴是绝对错误的。然而,如果您直接使用CoreGraphics进行绘制,请注意CoreGraphics确实使用翻转的Y轴(尽管在UIView子类或者我假设是CALayer代理中进行绘制时,CoreGraphics上下文已经被翻转以匹配UIView(或CALayer)的坐标系统)。
因此,简短的答案是,如果你能看到这里,那么CALayer的坐标系统应该与其对应的UIView的坐标系统匹配。

Kevin,如果你有时间的话,能否看一下我在下面帖子中列出的主线程。你似乎在这方面很有知识,任何见解都会受到赞赏。再次感谢。 - Corey Floyd

2

根据我的测试,我发现子层与其父层共享同一坐标系,因此如果您将子层添加到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)];


0

我认为UIView及其关联的图层的坐标系应该是相同的。然而,如果您自己创建图层,则坐标系会在垂直方向上翻转。


0
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;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接