2010-05-14 16 views
6

Tengo una serie de UIImages con los que necesito simular la profundidad. No puedo usar la escala porque necesito poder rotar la vista principal, y las imágenes deben verse como si estuvieran apiladas visiblemente una frente a la otra, no en el mismo plano.¿Cómo apilo imágenes para simular profundidad usando Core Animation?

hice un nuevo proyecto basado en ViewController y poner esto en el viewDidLoad (así como adjunta tres 120x120 imágenes de píxeles llamado 1.png, 2.png, y 3.png):

- (void)viewDidLoad { 

    // display image 3 
    UIImageView *three = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"3.png"]]; 
    three.center = CGPointMake(160 + 60, 240 - 60); 
    [self.view addSubview:three]; 

    // rotate image 3 around the z axis 
    // THIS IS INCORRECT 
    CATransform3D theTransform = three.layer.transform; 
    theTransform.m34 = 1.0/-1000; 
    three.layer.transform = theTransform; 

    // display image 2 
    UIImageView *two = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"2.png"]]; 
    two.center = CGPointMake(160, 240); 
    [self.view addSubview:two]; 

    // display image 1 
    UIImageView *one = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"1.png"]]; 
    one.center = CGPointMake(160 - 60, 240 + 60); 
    [self.view addSubview:one]; 

    // rotate image 3 around the z axis 
    // THIS IS INCORRECT 
    theTransform = one.layer.transform; 
    theTransform.m34 = 1.0/1000; 
    one.layer.transform = theTransform; 

    // release the images 
    [one release]; 
    [two release]; 
    [three release]; 

    // rotate the parent view around the y axis 
    theTransform = self.view.layer.transform; 
    theTransform.m14 = 1.0/-500; 
    self.view.layer.transform = theTransform; 

    [super viewDidLoad]; 
} 

I Tengo razones muy específicas por las que no estoy usando un EAGLView y por qué no estoy cargando las imágenes como CALayers (es decir, por qué estoy usando UIImageViews para cada una). Esta es solo una demostración rápida que puedo usar para calcular exactamente lo que necesito en mi aplicación principal.

¿Hay alguna forma de matriz para traducir estas 2d imágenes a lo largo del eje z para que se vean como lo que intento representar? He revisado los otros artículos de StackOverflow y las referencias de Wikipedia, y no he encontrado lo que estoy buscando, aunque es posible que no use necesariamente los términos correctos para lo que trato de hacer.

Respuesta

2

finalmente resolver esto mediante el uso CATransform3DMakeTranslation, que parece ser la única manera de mover una capa arriba o hacia abajo del eje z:

UIImageView *three = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"3.png"]]; 
three.layer.transform = CATransform3DMakeTranslation(0.0f, 0.0f, 20.0f); 
three.center = CGPointMake(160 + 60, 240 - 60); 
[self.view addSubview:three]; 

(I también se trasladó UIImageView uno pixeles -20.0f en el eje Z. Eso finalmente dio el efecto que estaba buscando.)

+0

Hola, estoy intentando tu código, pero no veo que la vista vaya en el eje Z según el valor que le damos. Mi requisito es tener un UIView alejamiento de la vista de la cámara en la dirección del eje Z. ¿Puedes compartir tu archivo completo? – Getsy

7

Para apilar sus vistas, y hacerlas aplicar la perspectiva, primero tendrá que colocarlas en diferentes posiciones Z, luego aplicar un efecto de perspectiva a la capa que las contiene.

creo que el siguiente código va a hacer esto, pero yo no lo he probado (que he hecho algo similar con CALayers puros, por lo que los principios generales son correctas):

- (void)viewDidLoad { 

    UIImageView *three = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"3.png"]]; 
    three.center = CGPointMake(160 + 60, 240 - 60); 
    [self.view addSubview:three]; 

    three.layer.zPosition = -100; 

    UIImageView *two = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"2.png"]]; 
    two.center = CGPointMake(160, 240); 
    [self.view addSubview:two]; 

    two.layer.zPosition = 0; 

    UIImageView *one = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"1.png"]]; 
    one.center = CGPointMake(160 - 60, 240 + 60); 
    [self.view addSubview:one]; 

    one.layer.zPosition = 100; 

    // release the images 
    [one release]; 
    [two release]; 
    [three release]; 

    CATransform3D theTransform = self.view.layer.sublayerTransform; 
    theTransform.m34 = 1.0/-500; 
    self.view.layer.sublayerTransform = theTransform; 

    [super viewDidLoad]; 
} 

En su código, solo está configurando la parte correspondiente de CATransform3D en la capa de cada vista (eso es lo que hace el componente m34 de la matriz CATransform3D). En realidad, no los está desplazando en el plano Z. Podría usar una transformación para esto, pero creo que la propiedad zPosition de sus CALayers proporciona una manera más limpia de ubicar las capas en 3-D.

Una vez que ha colocado las capas una respecto de la otra (con valores negativos que desaparecen del punto de vista del usuario), debe aplicar un efecto de perspectiva a todas las capas alojadas en su vista principal. Para esto, creo que es necesario establecer sublayerTransform de la capa de la vista de alojamiento para que la perspectiva se aplique correctamente a todas las capas alojadas.

Si desea rotar la serie de imágenes, use CATransform3DRotate() en la subcapaTransform de la capa de la vista de alojamiento principal.

Para una aplicación de ejemplo que realiza la manipulación en 3D de CALayers, con perspectiva aplicada a ellos, consulte el proyecto al que enlazo en la segunda actualización de mi artículo here.

+0

La subcapaTransform definitivamente ayudó, pero la zPosition no hizo nada. Parece que zPosition es como la propiedad de CSS z-index: cambia qué capas están encima de qué otras capas, pero no las mueve físicamente en el eje z. –

+0

@Jeffrey Berthiaume - De hecho, altera la ubicación de CALayers en espacio continuo en 3-D. Por ejemplo, vea este ejemplo: http://www.sunsetlakesoftware.com/sites/default/files/LayerExample2.compruebe y observe la ubicación de las capas roja, verde y azul. Altere las posiciones Z y podrá verlas apiladas en diferentes espaciamientos. Tenga en cuenta que la perspectiva se aplica en relación con el centro de la capa, por lo que las capas deben estar ligeramente desplazadas desde el centro para que pueda ver el apilamiento (o puede aplicar una rotación a la transformación de la subcapa). –

+0

Alteré las posiciones Z, y eso no pareció hacer nada (incluso cuando tuve que girar la vista principal). Todavía parecía que todo estaba plano uno encima del otro. Encontré esto: http://www.mmsguru.com/blogger/?action=entry&id=1242656318 "Además, un CALayer tiene una propiedad llamada zPosition ... Resulta que CoreAnimation, a pesar de que tiene todos esos atributos (z- coordenada a través de la propiedad de traducción y posición z) no permite el ocultamiento parcial de subcapas usando la tercera dimensión ... todas las subcapas de un toplayer son, finalmente, representadas en la misma capa ". –

Cuestiones relacionadas