2010-09-30 3 views
8

J'ai essayé de développer un objet « Vignettes » à base CALayer qui a deux couches qui font face à l'un de l'autre pour présenter les deux côtés d'une carte. Je travaille avec des choses comme la propriété doublesided du CALayer et de trouver les résultats à confusion. Ma classe de base est CALayer et j'ajouter deux sublayers à lui, l'un avec un M_PI/2 transformer et à la fois avec doublesided = NO mais tel qu'il est, je reçois la projection avant, peu importe la façon dont je tourne la carte et l'arrière ne montre pas du tout. Si je ne crée pas le devant, le dos montre à travers les deux côtés et le texte est dans un coin, pas 48 points et flou.Essayer de faire une carte de CALayers qui peut se retourner sur

Voici un lien vers une capture d'écran montrant la carte en train de terminer une révolution complète dans une vue UIViewController's. Vous voyez l'arrière du front. Cela devrait être invisible, et le dos doit être montrer ... Je pense ...

https://files.me.com/gazelips/lj2aqo


// CardView.h 

#import <Foundation/Foundation.h> 
#import <QuartzCore/QuartzCore.h> 

#define kCardWidth 100.0f 
#define kCardHeight 150.0f 

@interface CardView : CALayer { 
    CALayer *cardFront, *cardBack; 
} 

@property (nonatomic, retain) CALayer *cardFront, *cardBack; 

- (id)initWithPosition:(CGPoint)point; 
- (void)addPerspective; 
- (CALayer *)createFront; 
- (CALayer *)createBack; 

@end 

// CardView.m 

#import "CardView.h" 

@implementation CardView 

@synthesize cardFront, cardBack; 

static CATransform3D kPerspectiveTransform; 

- (id)initWithPosition:(CGPoint)point { 
    NSLog(@"--initWithPosition:CardView"); 
    self = [super init]; 
    if (self != nil) { 
     [self addPerspective]; 
     self.bounds = CGRectMake(0, 0, kCardWidth, kCardHeight); 
     self.position = point; 
     self.edgeAntialiasingMask = 0; 
     self.backgroundColor = [[UIColor clearColor] CGColor]; 
     self.borderColor = [[UIColor blackColor] CGColor]; 
     self.borderWidth = 0.5; 
     self.doubleSided = YES; 

     cardBack = [self createBack]; 
     [self addSublayer: cardBack]; 

     cardFront = [self createFront]; 
     [self addSublayer: cardFront]; 
    } 
    return self; 
} 

- (void)addPerspective { 
    NSLog(@"--prepare:CardView"); 
    kPerspectiveTransform = CATransform3DIdentity; 
    kPerspectiveTransform.m34 = -1.0/800.0; 
    self.transform = kPerspectiveTransform; 
} 

- (CALayer *)createFront { 
    NSLog(@"--createFront:CardView"); 
    CALayer *front = [[CALayer alloc] init]; 
    front.bounds = CGRectMake(0.0f, 0.0f, kCardWidth, kCardHeight); 
    front.position = CGPointMake(kCardWidth/2, kCardHeight/2); 
    front.edgeAntialiasingMask = 0; 
    front.backgroundColor = [[UIColor whiteColor] CGColor]; 
    front.cornerRadius = 8 * (kCardHeight/150); 
    front.borderWidth = 1; 
    front.borderColor = [[UIColor grayColor] CGColor]; 
    front.doubleSided = NO; 

    return [front autorelease]; 
} 

- (CALayer *)createBack { 
    NSLog(@"--createBack:CardView"); 
    CALayer *back = [[CALayer alloc] init]; 
    back.bounds = CGRectMake(0.0f, 0.0f, kCardWidth, kCardHeight); 
    back.position = CGPointMake(kCardWidth/2, kCardHeight/2); 
    back.backgroundColor = [[UIColor blueColor] CGColor]; 
    back.contentsGravity = kCAGravityResize; 
    back.masksToBounds = YES; 
    back.borderWidth = 4 * (kCardHeight/150); 
    back.borderColor = [[UIColor grayColor] CGColor];; 
    back.cornerRadius = 8 * (kCardHeight/150); 
    back.edgeAntialiasingMask = 0; 
    back.doubleSided = NO; 

    CATextLayer *textLayer = [CATextLayer layer]; 
    textLayer.font = [UIFont boldSystemFontOfSize:48]; 
    textLayer.bounds = CGRectMake(0.0f, 0.0f, kCardWidth, kCardHeight); 
    textLayer.position = CGPointMake(50.0f, 75.0f); 
    textLayer.string = @"Steve"; 
    [back addSublayer:textLayer]; 

    back.transform = CATransform3DMakeRotation(M_PI, 0.0f, 1.0f, 0.0f); 
    return [back autorelease]; 
} 

@end 

Répondre

23

L'astuce a fini par être l'utilisation de CATransformLayer. Ceci est une couche qui est juste pour contenir d'autres couches (il ne peut pas avoir des choses comme backgroundColor ou borderWidth). Il maintient cependant la vraie relation 3D de ses couches enfant (c'est-à-dire, il ne les aplatit pas comme un CALayer régulier). Donc, vous pouvez faire deux couches, retourner un seul et compenser ses zPosition juste un cheveu et les mettre tous les deux dans un CATransformLayer et maintenant vous pouvez retourner ce calque parent de six façons à partir de dimanche et les calques enfants restent verrouillés ensemble et restituent toujours correctement. Frais généraux assez doux et bas!

+3

Si vous cherchez un bon tutoriel à ce sujet, cela m'a vraiment aidé: http://invasivecode.tumblr.com/post/29307073330/core-animation-transform-layer – Marc

+0

A dû remettre en cause ceci non seulement parce que c'est la bonne réponse, mais aussi pour l'utilisation de "six façons de dimanche" – ribeto

1

Il y a une façon beaucoup plus facile de faites ceci, aussi longtemps que vous essayez seulement de faire un «flip» normal.

Regardez dans le système d'animation UIView, et il y a un 'transitionWithView'. Vous pouvez appliquer une animation flip à cet endroit, et cela produira le même effet, avec pratiquement aucun travail.

+0

Merci! J'ai déjà une version (c'est le numéro 6, je pense) qui utilise un UIView et je peux le retourner sur les 3 axes pendant que je le déplace. Je viens de faire un UIView et j'ai ajouté sa couche à mon ViewController. Mais je n'arrivais pas à comprendre la chose à double face. – Steve

+0

J'aimerais voir la solution avec laquelle vous êtes finalement allé. – Marvo

0

Je lis aussi beaucoup des versions pour UIView. Après les avoir assemblés tous ensemble, c'est ce que j'ai obtenu et cela fonctionne.

Pour configurer je mis

1) la carte sous constructeur d'interface avec un objet vue qui contient un objet UIImageView qui montre l'avant de la carte. donc View-> View-> UIImageView-> fichier image du recto de la carte

2) Ensuite, l'objet View contenant UIImageView est changé en UIController Class (pour qu'il réponde aux touches).

3) Dans le fichier d'en-tête de la viewcontroller, j'ai créé IBOutlet UIImageView Vignettes lié à la UIImageView et un Flipcard IBAction lié à l'objet View (qui est maintenant un objet UIController) par événement « touch down ».

4) IBAction flipCard est implémenté en créant dynamiquement un autre objet View subview contenant un autre UIImageView, mais init avec l'image backside

5) en utilisant CGRect, le cadre et le centre de l'objet arrière sont alignés avec l'avant.6) alors les méthodes d'animation de UIView sont appelées pour échanger les sous-vues avec l'animation.

Et cela fait l'affaire.

Je ne suis pas chez mon mac en ce moment, donc je n'ai pas les codes. Si quelqu'un est intéressé, je peux poster plus tard.

+0

salut boobami, im intéressant dans votre code ... pouvez-vous le poster? merci – sundsx

+0

Cela fait un moment mais laissez-moi essayer de le trouver. – boobami

Questions connexes