Converter um CGPoint de um UIView sistema de coordenadas para um sistema de coordenadas CALayer

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

Pergunta

Existem métodos para transferir um CGPoint de um UIView para outro e de um CALayer para outro. Não consigo encontrar uma maneira de mudar a CGPoint do sistema de coordenadas de um UIView para sistema de coordenadas de um CALayer.

Será que uma camada e de exibição de host têm o mesmo sistema de coordenadas? Eu preciso para transformar pontos entre eles?

Obrigado, Corey

[EDIT]

Obrigado pela resposta! É difícil encontrar informações sobre as diferenças / semelhanças entre CA no iPhone e Mac. Estou surpreso que eu não poderia encontrar esta questão abordada diretamente em qualquer documentação Apple.

Eu estava perseguindo essa resposta para ajudar com um bug que estou a solução de problemas, e este foi até agora o meu melhor palpite, mas acho que estou latindo para a árvore errada. Se os sistemas de coordenadas são os mesmos, então eu tenho uma outra questão ...

A questão real que eu estou tendo pode ser encontrada aqui no estouro de pilha: teste de ocorrência única retornando camada quando a metade inferior da camada é tocado

Foi útil?

Solução

Você pode definir a propriedade transform de CALayers para a transformação adequada se você deseja inverter seu sistema de coordenadas, mas nota que isso provavelmente vai virar seu desenho do contents bem (eu não testei isso, mas faz sentido que isso seria verdade). Minha afirmação de que o CALayer associado com ações UIView o mesmo sistema de coordenadas poderia de fato ser totalmente errônea. Também poderia ser que CALayers usar o mesmo sistema de coordenadas como UIViews (ou seja, eles nunca virado verticalmente), mas eu pensei que eles eram uma vez CoreGraphics usa uma capotou sistema de coordenadas em relação ao UIKit.

Uma maneira simples de teste seria para adicionar um CALayer tamanho de tela, como a subcamada da camada de um ponto de vista, em seguida, adicione outra pequena CALayer como uma subcamada disso. Você pode configurá-lo para mostrar-se em (0, 0, 320, 100) e ver se ele aparece na parte superior ou na parte inferior da tela do iPhone. Isso vai lhe dizer em que direção o eixo Y vai 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];
}

Eu só realizado este teste eu mesmo, e parece CALayers realmente usar o mesmo sistema de coordenadas como UIViews, por isso a minha afirmação de que aleta de CALayer eixo Y é definitivamente errado. No entanto, se você desenhar com CoreGraphics diretamente, estar ciente de que CoreGraphics não usar um eixo Y invertido (embora ao desenhar em um UIView subclasse ou, presumo, um delegado CALayer, o contexto CoreGraphics já foi virado para coincidir com o do UIView (ou de CALayer) sistema de coordenadas).

Portanto, a resposta curta, se você chegou até aqui, é o sistema de coordenadas para CALayer deve coincidir com o sistema de coordenadas para seu correspondente UIView.

Outras dicas

A documentação para hitTest diz:

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

Assim que você precisa fazer (algo assim):

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

Em termos de documentação da Apple, eu encontrei um "iPhone OS nota" na camada de seção do sistema do core Animation Guia de Programação (2008-11-13).

A camada de raiz padrão de uma instância de UIView usa um sistema virado coordenadas que corresponde ao padrão do sistema de uma instância-o UIView origem de coordenadas está no canto superior esquerdo e valores aumentam para baixo e para a direita. Camadas criadas por instanciar CALayer usar diretamente o padrão Core Animation sistema de coordenadas.

De meus testes eu descobri que sublayers compartilham o mesmo sistema de coordenadas como de camada pai e, portanto, se você estiver adicionando subcamada a uma camada UIView, em seguida, eles irão compartilhar o mesmo sistema de coordenadas.

No caso de você ainda quer virar o sistema de coordenadas de modo a que a sua origem é no canto superior esquerdo você deve usar essa transformação que inverte o eixo y. (X, y, 1) = (x 'y', 1) * [1 0 0], [0 -1 0], [0 ALTURA 1]

que traduzido para o código é: [Your_layer setAffineTransform: CGAffineTransformMake (1,0,0, -1,0, ALTURA)];

Eu acredito que o sistema de coordenadas de um UIView e sua camada associado deve ser o mesmo. No entanto, se você criar camadas mesmo, o sistema de coordenadas é invertida 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;
}

Eu acredito que os dois têm o mesmo sistema de coordenadas.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top