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

StackOverflow https://stackoverflow.com/questions/410278

Вопрос

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

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

Спасибо, Кори

[РЕДАКТИРОВАТЬ]

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

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

Реальную проблему, с которой я столкнулся, можно найти здесь, в Stack Overflow:Тест на попадание слоя возвращает слой только при касании нижней половины слоя

Это было полезно?

Решение

Вы можете установить 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];
}

Я только что сам выполнил этот тест, и оказалось, что CALayer на самом деле использует ту же систему координат, что и 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» в разделе «Система координат слоев» Руководство по программированию базовой анимации (2008-11-13).

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

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

Я считаю, что система координат 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;
}

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top