iphone - español - core animation swift
Convierta un CGPoint de un sistema de coordenadas UIView a un sistema de coordenadas CALayer (7)
Existen 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 del sistema de coordenadas de UIView al sistema de coordenadas de un 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 esta era hasta ahora 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 la capa que solo devuelve la capa cuando se toca la mitad inferior de la capa
Creo que los dos tienen el mismo sistema de coordenadas.
Creo que el sistema de coordenadas de una UIView y su capa asociada debería ser el mismo. Sin embargo, si crea capas usted mismo, el sistema de coordenadas se voltea verticalmente.
Puede establecer la propiedad de transform
de CALayers en la transformación adecuada si desea voltear su sistema de coordenadas, pero tenga en cuenta que probablemente también volteará su dibujo de los contents
(no lo he probado, pero tiene sentido que esto sea cierto). Mi afirmación de que el CALayer asociado a una UIView comparte el mismo sistema de coordenadas podría de hecho ser completamente erróneo. También podría ser que los CALayers usan el mismo sistema de coordenadas que UIViews (es decir, nunca se voltean verticalmente), pero pensé que sí, ya que CoreGraphics utiliza un sistema de coordenadas volteado relativo a UIKit.
Una forma simple de probar sería agregar un CALayer del tamaño de una pantalla como la subcapa de la capa de una vista, luego agregar otro CALayer pequeño como una 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 te 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];
}
Acabo de realizar esta prueba yo mismo, y parece que los CALayers realmente usan el mismo sistema de coordenadas que UIViews, por lo que mi afirmación de que CALayer voltea el eje Y es definitivamente incorrecta. Sin embargo, si dibuja con CoreGraphics directamente, tenga en cuenta que CoreGraphics utiliza un eje Y invertido (aunque al dibujar en una subclase UIView o, supongo, un delegado CALayer, el contexto CoreGraphics ya se ha volteado para coincidir con el de UIView (o Sistema de coordenadas CALayer).
Entonces, la respuesta corta, si llegó hasta aquí, es que el sistema de coordenadas para CALayer debe coincidir con el sistema de coordenadas para su UIView correspondiente.
La documentación de 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 debes hacer algo como esto:
CGPoint thePoint = [touch locationInView:self];
thePoint = [self.layer convertPoint:thePoint toLayer:self.layer.superlayer];
CALayer *theLayer = [self.layer hitTest:thePoint];
De mis pruebas descubrí que las subcapas comparten el mismo sistema de coordenadas que su capa principal y, por lo tanto, si está agregando subcapa a una capa UIView, entonces compartirán el mismo sistema de coordenadas.
En caso de que aún desee voltear el sistema de coordenadas para que su origen esté en la esquina superior izquierda, debe usar esta transformación que gira 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, heigth)];
En cuanto a la documentación de Apple, encontré una "Nota del sistema operativo del iPhone" en la sección del Sistema de coordenadas de la capa de la Guía de programación de animación principal (2008-11-13).
La capa raíz predeterminada de una instancia de UIView utiliza un sistema de coordenadas volteado que coincide con el sistema de coordenadas predeterminado de una instancia de UIView: el origen está en la esquina superior izquierda y los valores aumentan hacia abajo y hacia la derecha. Las capas creadas al crear instancias de CALayer usan directamente el sistema de coordenadas Core Animation estándar.
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;
}