【问题标题】:Convert a CGPoint from a UIView coordinate system to a CALayer coordinate system将 CGPoint 从 UIView 坐标系转换为 CALayer 坐标系
【发布时间】:2009-01-04 01:57:21
【问题描述】:

有一些方法可以将 CGPoint 从一个 UIView 传输到另一个 UIView 以及从一个 CALayer 传输到另一个。我找不到将 CGPoint 从 UIView 的坐标系更改为 CALayer 的坐标系的方法。

图层和它的宿主视图是否具有相同的坐标系?我需要在它们之间转换点吗?

谢谢, 科里

[编辑]

感谢您的回答!很难找到有关 iPhone 和 Mac 上 CA 之间差异/相似之处的信息。我很惊讶我无法在任何 Apple 文档中直接解决这个问题。

我一直在寻求这个答案以帮助解决我正在排除故障的错误,这是迄今为止我最好的猜测,但我想我是在找错误的树。如果坐标系相同,那么我还有另一个问题......

我遇到的实际问题可以在 Stack Overflow 上找到: layer hit test only returning layer when bottom half of layer is touched

【问题讨论】:

    标签: iphone cocoa-touch core-animation


    【解决方案1】:

    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。但它确实有效。谢谢!
    【解决方案2】:

    在 Apple 文档方面,我在 Core Animation Programming Guide (2008-11-13) 的图层坐标系部分找到了“iPhone OS Note”。

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

    【讨论】:

      【解决方案3】:

      如果您想翻转坐标系,可以将 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];
      }
      

      我自己刚刚进行了这个测试,看起来 CALayer 实际上使用与 UIViews 相同的坐标系,所以我断言 CALayer 翻转 Y 轴肯定是错误的。但是,如果您直接使用 CoreGraphics 进行绘图,请注意 CoreGraphics 确实使用翻转的 Y 轴(尽管在 UIView 子类或我假设 CALayer 委托中绘图时,CoreGraphics 上下文已经翻转以匹配 UIView 的(或 CALayer 的)坐标系)。

      所以简短的回答是,如果你做到了这一步,CALayer 的坐标系应该与其对应的 UIView 的坐标系相匹配。

      【讨论】:

      • 凯文,如果你有时间,你介意看看我在下面的帖子中列出的主线程。您似乎对此非常了解,任何见解都值得赞赏。再次感谢
      【解决方案4】:

      从我的测试中,我发现子图层与其父图层共享相同的坐标系,因此如果您将子图层添加到 UIView 图层,那么它们将共享相同的坐标系。

      如果您仍想翻转坐标系,使其原点位于左上角,您应该使用翻转 y 轴的转换。 (x,y,1) = (x', y', 1) * [1 0 0],[0 -1 0],[0 高度 1]

      翻译成代码的是: [your_layer setAffineTransform:CGAffineTransformMake(1,0,0,-1,0,heigth)];

      【讨论】:

        【解决方案5】:

        我相信 UIView 的坐标系和它的关联层应该是相同的。但是,如果您自己创建图层,则坐标系会垂直翻转。

        【讨论】:

          【解决方案6】:
          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;
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-03-14
            • 1970-01-01
            • 1970-01-01
            • 2019-06-23
            • 2012-09-06
            相关资源
            最近更新 更多