Conversion d'un CGPoint d'un système de coordonnées UIView en un système de coordonnées CALayer

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

Question

Il existe des méthodes pour transférer un CGPoint d'un UIView à un autre et d'un CALayer à un autre. Je ne trouve pas le moyen de changer un CGPoint d'un système de coordonnées UIView à un système de coordonnées CALayer.

Une couche et sa vue hôte ont-elles le même système de coordonnées? Dois-je transformer des points entre eux?

Merci, Corey

[EDIT]

Merci pour la réponse! Il est difficile de trouver des informations sur les différences / similitudes entre CA sur iPhone et Mac. Je suis surpris de ne pouvoir trouver ce problème directement dans aucune documentation Apple.

Je cherchais cette réponse pour aider avec un bogue que je corrige, et c’était pour le moment ma meilleure hypothèse, mais je suppose que j’aborde le mauvais arbre. Si les systèmes de coordonnées sont les mêmes, j’ai un autre problème ...

Le problème que je rencontre peut être trouvé ici sur Stack Overflow: test d'accès de couche uniquement couche de retour lorsque la moitié inférieure de la couche est touchée

Était-ce utile?

La solution

Vous pouvez définir la propriété transformation de CALayers sur la transformation appropriée si vous souhaitez inverser leur système de coordonnées, mais notez que cela retournera probablement leur dessin du contenu . aussi (je n'ai pas testé cela, mais il est logique que cela soit vrai). Mon assertion selon laquelle la couche CALayer associée à UIView partage le même système de coordonnées pourrait en réalité être totalement erronée. Il se peut également que CALayers utilise le même système de coordonnées que UIViews (c’est-à-dire qu’ils ne sont jamais inversés verticalement), mais je pensais que oui, car CoreGraphics utilise un système de coordonnées inversé par rapport à UIKit.

Un moyen simple de tester consiste à ajouter une CALayer de la taille d'un écran en tant que sous-couche d'un calque de vue, puis à ajouter une autre petite CALayer en tant que sous-couche de celle-ci. Vous pouvez le configurer pour qu'il s'affiche à (0, 0, 320, 100) et voir s'il apparaît en haut ou en bas de l'écran de l'iPhone. Cela vous indiquera la direction prise par l’axe Y pour 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];
}

Je viens d'effectuer ce test moi-même, et il semble que CALayers utilise en fait le même système de coordonnées que UIViews, mon affirmation selon laquelle l'inversion de l'axe Y de CALayer est définitivement fausse. Cependant, si vous dessinez directement avec CoreGraphics, sachez que CoreGraphics utilise un axe Y retourné (bien que lors du dessin dans une sous-classe UIView ou, je suppose, un délégué CALayer, le contexte CoreGraphics a déjà été inversé pour correspondre au système de coordonnées de UIView (ou de CALayer)).

Donc, si vous en arrivez là, la réponse courte est que le système de coordonnées de CALayer doit correspondre au système de coordonnées de la vue UIV correspondante.

Autres conseils

La documentation de hitTest indique:

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

Donc, vous devez faire (quelque chose comme ceci):

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

En termes de documentation Apple, j'ai trouvé un "iPhone OS Note". dans la section Système de coordonnées de couche du Guide de programmation d'animation de base (2008-11-13).

  

La couche racine par défaut d'une instance UIView utilise un système de coordonnées retourné qui correspond au système de coordonnées par défaut d'une instance UIView: l'origine est en haut à gauche et les valeurs augmentent en bas et à droite. Les calques créés en instanciant CALayer utilisent directement le système de coordonnées standard de Core Animation.

D'après mes tests, j'ai découvert que les sous-couches partagent le même système de coordonnées que la couche parente. Par conséquent, si vous ajoutez une sous-couche à une couche UIView, elles partagent le même système de coordonnées.

Si vous souhaitez toujours inverser le système de coordonnées de sorte que son origine se trouve dans le coin supérieur gauche, vous devez utiliser cette transformation qui inverse l’axe des y. (x, y, 1) = (x ', y', 1) * [1 0 0], [0 -1 0], [0 hauteur 1]

qui traduit en code est: [your_layer setAffineTransform: CGAffineTransformMake (1,0,0, -1,0, hauteur)];

Je pense que le système de coordonnées d’un UIView et de sa couche associée devrait être identique. Cependant, si vous créez vous-même des calques, le système de coordonnées est inversé verticalement.

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

Je crois que les deux ont le même système de coordonnées.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top