Преобразование CGPoint из системы координат UIView в систему координат CALayer

Существуют методы переноса CGPoint с одного UIView на другой и с одного CALayer на другой. Я не могу найти способ изменить CGPoint из системы координат UIView в систему координат CALayer.

Существует ли у одного и того же вида хоста одна и та же система координат? Нужно ли мне преобразовывать точки между ними?

Спасибо, Corey

[EDIT]

Спасибо за ответ! Трудно найти информацию о различиях/сходствах между CA на iPhone и Mac. Я удивлен, что я не мог найти эту проблему напрямую в любой документации Apple.

Я преследовал этот ответ, чтобы помочь с ошибкой, которую я искал, и это было до сих пор моим лучшим предположением, но я полагаю, что я лаяю неправильное дерево. Если системы координат одинаковы, то у меня есть еще одна проблема...

Фактическая проблема, с которой я столкнулась, можно найти здесь в разделе "Переполнение стека": layer hit test возвращает только слой, когда затрагивается нижняя половина слоя

Ответ 1

Вы можете установить свойство transform для CALayers на соответствующее преобразование, если вы хотите перевернуть их систему координат, но обратите внимание, что это, вероятно, также изменит их рисунок contents (я не тестировал это, но имеет смысл, что это будет правда). Мое утверждение о том, что CALayer, связанный с UIView, имеет одну и ту же систему координат, на самом деле может быть полностью ошибочным. Также может быть, что CALayers используют ту же систему координат, что и UIViews (т.е. Они никогда не перевернуты вертикально), но я думал, что они с тех пор, как CoreGraphics использует перевернутую систему координат относительно UIKit.

Простым способом тестирования было бы добавить CALayer размера экрана в качестве подуровня слоя вида, а затем добавить еще один небольшой CALayer в качестве подслоя. Вы можете настроить его на отображение (0, 0, 320, 100) и посмотреть, отображается ли оно вверху или внизу экрана iPhone. Это скажет вам, в каком направлении идет ось Y для CoreAnimation.

- (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.

Ответ 2

В документации для 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 superlayer. */

Итак, вам нужно сделать (что-то вроде этого):

CGPoint thePoint = [touch locationInView:self];
thePoint = [self.layer convertPoint:thePoint toLayer:self.layer.superlayer];
CALayer *theLayer = [self.layer hitTest:thePoint];

Ответ 3

Что касается документации Apple, я нашел "примечание к iPhone OS" в разделе "Система координат слоя" Core Руководство по программированию анимации (2008-11-13).

По умолчанию в корневом слое UIView используется перевернутая система координат, которая соответствует системе координат по умолчанию экземпляра UIView - начало находится в левом верхнем углу, а значения возрастают вниз и вправо. Слои, созданные путем создания CALayer напрямую, используют стандартную систему координат Core Animation.

Ответ 4

Из моих тестов я обнаружил, что подслои используют одну и ту же систему координат, что и ее родительский слой, поэтому, если вы добавляете подуровень в слой 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)];

Ответ 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;
}

Ответ 7

Я считаю, что у двух есть одна и та же система координат.