Convierta un CGPoint de un sistema de coordenadas UIView a un sistema de coordenadas CALayer

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

Pregunta

Hay métodos para transferir un CGPoint de un UIView a otro y de un CALayer a otro. No puedo encontrar una manera de cambiar un CGPoint de un sistema de coordenadas de UIView a un sistema de coordenadas de CALayer.

¿Una capa y su vista de host tienen el mismo sistema de coordenadas? ¿Necesito transformar puntos entre ellos?

Gracias, Corey

[EDITAR]

Gracias por la respuesta! Es difícil encontrar información sobre las diferencias / similitudes entre CA en el iPhone y Mac. Me sorprende que no haya podido encontrar este problema directamente en ninguna documentación de Apple.

Estaba buscando esta respuesta para ayudar con un error que estoy solucionando, y hasta ahora esta era mi mejor suposición, pero supongo que estoy ladrando el árbol equivocado. Si los sistemas de coordenadas son iguales, entonces tengo otro problema ...

El problema real que tengo se puede encontrar aquí en Stack Overflow: prueba de impacto de capa solamente devolver la capa cuando se toca la mitad inferior de la capa

¿Fue útil?

Solución

Puede establecer la propiedad transform de CALayers en la transformación adecuada si desea cambiar su sistema de coordenadas, pero tenga en cuenta que esto probablemente cambiará su dibujo de los contenidos de también (no lo he probado, pero tiene sentido que esto sea cierto). Mi afirmación de que el CALayer asociado con un UIView comparte el mismo sistema de coordenadas podría, de hecho, ser completamente erróneo. También podría ser que los CALayer usen el mismo sistema de coordenadas que UIViews (es decir, nunca se voltean verticalmente), pero pensé que lo eran ya que CoreGraphics usa un sistema de coordenadas volteado relativo a UIKit.

Una forma sencilla de probar sería agregar un CALayer de tamaño de pantalla como subcapa de la capa de una vista, y luego agregar otro CALayer pequeño como subcapa de eso. Puede configurarlo para que aparezca en (0, 0, 320, 100) y ver si aparece en la parte superior o inferior de la pantalla del iPhone. Esto le dirá en qué dirección va el eje Y para 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];
}

Yo mismo realicé esta prueba, y parece que los CALayer realmente usan el mismo sistema de coordenadas que UIViews, por lo que mi afirmación de que CALayer gira el eje Y es definitivamente errónea. Sin embargo, si dibuja con CoreGraphics directamente, tenga en cuenta que CoreGraphics hace utiliza un eje Y volteado (aunque al dibujar en una subclase UIView o, supongo, un delegado CALayer, el contexto CoreGraphics ya ha sido volteado para coincidir con el sistema de coordenadas de UIView (o CALayer's)).

Entonces, la respuesta corta, si llegaste hasta aquí, es que el sistema de coordenadas para CALayer debe coincidir con el sistema de coordenadas para su UIView correspondiente.

Otros consejos

La documentación para hitTest dice:

/* 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. */

Entonces necesitas hacer (algo como esto):

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

En cuanto a la documentación de Apple, encontré una " Nota de SO de iPhone " en la sección Sistema de coordenadas de capas de Guía de programación de animaciones básicas (2008-11-13).

  

La capa raíz predeterminada de una instancia de UIView utiliza un sistema de coordenadas invertido que coincide con el sistema de coordenadas predeterminado de una instancia de UIView: el origen se encuentra en la parte superior izquierda y los valores aumentan hacia abajo y hacia la derecha. Las capas creadas al crear una instancia de CALayer utilizan directamente el sistema de coordenadas de Core Animation estándar.

De mis pruebas descubrí que las subcapas comparten el mismo sistema de coordenadas que su capa principal y, por lo tanto, si estás agregando una subcapa a una capa UIView, compartirán el mismo sistema de coordenadas.

En caso de que aún quieras cambiar el sistema de coordenadas para que su origen se encuentre en la esquina superior izquierda, debes usar esta transformación que invierte el eje y. (x, y, 1) = (x ', y', 1) * [1 0 0], [0 -1 0], [0 altura 1]

que traducido al código es: [your_layer setAffineTransform: CGAffineTransformMake (1,0,0, -1,0, altura)];

Creo que el sistema de coordenadas de una UIView y su capa asociada deberían ser iguales. Sin embargo, si crea capas usted mismo, el sistema de coordenadas se voltea verticalmente.

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

Creo que los dos tienen el mismo sistema de coordenadas.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top