2012-11-12 13 views
10

Ich spiele mit Brad Larsen's adaption der Trackball App.
Ich habe zwei Ansichten in einem 60-Grad-Winkel zueinander und fragte mich, wie ich die Rotation in die Mitte dieses (nicht geschlossenen) Rechtecks ​​bringen könnte?Rechteck um Mitte drehen

In den folgenden Bildern hätte ich mir gewünscht, dass die Rotation innerhalb der blauen Linien stattfindet.

enter image description here enter image description here enter image description here

-Code (nur um die x-Achse drehen modifiziert):

#import "MyView.h" 

//===================================================== 
// Defines 
//===================================================== 

#define DEGREES_TO_RADIANS(degrees) \ 
    (degrees * (M_PI/180.0f)) 

//===================================================== 
// Public Interface 
//===================================================== 

@implementation MyView 

- (void)awakeFromNib 
{ 
    transformed = [CALayer layer]; 
    transformed.anchorPoint = CGPointMake(0.5f, 0.5f); 

    transformed.frame = self.bounds; 
    [self.layer addSublayer:transformed]; 

    CALayer *imageLayer = [CALayer layer]; 
    imageLayer.frame = CGRectMake(10.0f, 4.0f, self.bounds.size.width/2.0f, self.bounds.size.height/2.0f); 
    imageLayer.transform = CATransform3DMakeRotation(DEGREES_TO_RADIANS(60.0f), 1.0f, 0.0f, 0.0f); 
    imageLayer.contents = (id)[[UIImage imageNamed:@"IMG_0051.png"] CGImage]; 
    imageLayer.borderColor = [UIColor yellowColor].CGColor; 
    imageLayer.borderWidth = 2.0f; 
    [transformed addSublayer:imageLayer]; 

    imageLayer = [CALayer layer]; 
    imageLayer.frame = CGRectMake(10.0f, 120.0f, self.bounds.size.width/2.0f, self.bounds.size.height/2.0f); 
    imageLayer.transform = CATransform3DMakeRotation(DEGREES_TO_RADIANS(-60.0f), 1.0f, 0.0f, 0.0f); 
    imageLayer.contents = (id)[[UIImage imageNamed:@"IMG_0089.png"] CGImage]; 
    imageLayer.borderColor = [UIColor greenColor].CGColor; 
    imageLayer.borderWidth = 2.0f; 

    transformed.borderColor = [UIColor whiteColor].CGColor; 
    transformed.borderWidth = 2.0f; 
    [transformed addSublayer:imageLayer]; 

    UIView *line = [[UIView alloc] initWithFrame:CGRectMake(0, self.bounds.size.height/2.0f, self.bounds.size.width, 2)]; 
    [line setBackgroundColor:[UIColor redColor]]; 
    [self addSubview:line]; 

    line = [[UIView alloc] initWithFrame:CGRectMake(0, self.bounds.size.height * (1.0f/4.0f), self.bounds.size.width, 2)]; 
    [line setBackgroundColor:[UIColor blueColor]]; 
    [self addSubview:line]; 

    line = [[UIView alloc] initWithFrame:CGRectMake(0, self.bounds.size.height * (3.0f/4.0f), self.bounds.size.width, 2)]; 
    [line setBackgroundColor:[UIColor blueColor]]; 
    [self addSubview:line]; 
} 

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    previousLocation = [[touches anyObject] locationInView:self]; 
} 

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    CGPoint location = [[touches anyObject] locationInView:self]; 
    //location = CGPointMake(previousLocation.x, location.y); 

    CATransform3D currentTransform = transformed.sublayerTransform; 

    //CGFloat displacementInX = location.x - previousLocation.x; 
    CGFloat displacementInX = previousLocation.x - location.x; 
    CGFloat displacementInY = previousLocation.y - location.y; 

    CGFloat totalRotation = sqrt((displacementInX * displacementInX) + (displacementInY * displacementInY)); 

    CGFloat angle = DEGREES_TO_RADIANS(totalRotation); 
    CGFloat x = ((displacementInX/totalRotation) * currentTransform.m12 + (displacementInY/totalRotation) * currentTransform.m11); 

    CATransform3D rotationalTransform = CATransform3DRotate(currentTransform, angle, x, 0, 0); 

    previousLocation = location; 
    transformed.sublayerTransform = rotationalTransform; 
} 

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 
} 

- (void)dealloc { 
    [super dealloc]; 
} 

@end 
+0

ich Brads Code verwenden wie - versucht, verschiedene Tests mit wechselnden Ankerpunkten, aber ohne Glück – ESoft

+0

alles an seinem Platz :-) – ESoft

+0

den Ankerpunkt auf Mitte gesetzt und dann drehen. –

Antwort

2

Sie müssen die imageLayer.zPosition von einstellen jede der Dreiecksseiten zu der Entfernung von der Mitte des Dreiecks (das in Ihrem Fall ein gleichseitiges Dreieck ist).

Wenn sideHeight = self.bounds.size.height/2.0f;
Dann distanceFromCenter = ((sideHeight/2.0f)/sqrt(3));

Auch wenn die Rotation auf den Seiten einstellen, müssen Sie sie in ihre gewünschten Positionen bewegen (im Code sind sie fest einprogrammiert).

Aktualisiert-Code

- (void)awakeFromNib 
{ 
    transformed = [CALayer layer]; 
    transformed.anchorPoint = CGPointMake(0.5f, 0.5f); 

    transformed.frame = self.bounds; 
    [self.layer addSublayer:transformed]; 

    CGFloat sideHeight = self.bounds.size.height/2.0f; 
    CGFloat distanceFromCenter = ((sideHeight/2.0f)/sqrt(3)); 

    CGFloat sideC = sideHeight/2.0f; 
    CGFloat sideA = sideC/2.0f; 
    CGFloat sideB = (sqrt(3) * sideA); 

    CALayer *imageLayer = [CALayer layer]; 
    imageLayer.frame = CGRectMake(10.0f, (self.bounds.size.height/2.0f) - (sideHeight/2.0f), self.bounds.size.width/2.0f, sideHeight); 
    imageLayer.transform = CATransform3DConcat(CATransform3DMakeRotation(-DEGREES_TO_RADIANS(60.0f), 1.0f, 0.0f, 0.0f), 
               CATransform3DMakeTranslation(0, -sideA, -sideB)); 
    imageLayer.contents = (id)[[UIImage imageNamed:@"IMG_0051.png"] CGImage]; 
    imageLayer.borderColor = [UIColor yellowColor].CGColor; 
    imageLayer.borderWidth = 2.0f; 
    imageLayer.zPosition = distanceFromCenter; 
    [transformed addSublayer:imageLayer]; 

    imageLayer = [CALayer layer]; 
    imageLayer.frame = CGRectMake(10.0f, (self.bounds.size.height/2.0f) - (sideHeight/2.0f), self.bounds.size.width/2.0f, sideHeight); 
    imageLayer.transform = CATransform3DConcat(CATransform3DMakeRotation(DEGREES_TO_RADIANS(60.0f), 1.0f, 0.0f, 0.0f), 
               CATransform3DMakeTranslation(0, sideA, -sideB)); 
    imageLayer.contents = (id)[[UIImage imageNamed:@"IMG_0089.png"] CGImage]; 
    imageLayer.borderColor = [UIColor greenColor].CGColor; 
    imageLayer.zPosition = distanceFromCenter; 
    imageLayer.borderWidth = 2.0f; 

    transformed.borderColor = [UIColor whiteColor].CGColor; 
    transformed.borderWidth = 2.0f; 
    [transformed addSublayer:imageLayer]; 

    UIView *line = [[UIView alloc] initWithFrame:CGRectMake(0, self.bounds.size.height/2.0f, self.bounds.size.width, 2)]; 
    [line setBackgroundColor:[UIColor redColor]]; 
    [self addSubview:line]; 

    line = [[UIView alloc] initWithFrame:CGRectMake(0, self.bounds.size.height * (1.0f/4.0f), self.bounds.size.width, 2)]; 
    [line setBackgroundColor:[UIColor blueColor]]; 
    [self addSubview:line]; 

    line = [[UIView alloc] initWithFrame:CGRectMake(0, self.bounds.size.height * (3.0f/4.0f), self.bounds.size.width, 2)]; 
    [line setBackgroundColor:[UIColor blueColor]]; 
    [self addSubview:line]; 
} 
1

Verwendung auch andere Transformation (ich glaube, Sie Übersetzung benötigen) und verketten sie mit Rotation. Dieses Beispiel skaliert auch das Bild, so dass Sie eine skalierte erhalten, verschoben und gedreht Schicht:

CATransform3D translate = CATransform3DMakeTranslation(yourShiftByX, yourShiftByY, 0); 
CATransform3D scale = CATransform3DMakeScale(yourRateX, yourRateY, 1); 
CATransform3D rotate = CATransform3DMakeRotation(DEGREES_TO_RADIANS(60.0f), 1.0, 0.0, 0.0); 
CATransform3D transform = CATransform3DConcat(CATransform3DConcat(rotate, scale), translate); 
// the order is important: FIRST we rotate, THEN we scale and AT LAST we position the object 

// now apply 'transform' to your layer 
0

sollten Sie Ihre Imageview superview, um die Perspektive zu zeigen:

CATransform3D tranfrom = CATransform3DIdentity; 
tranfrom.m34 = -1.0/z; 
imageView.superview.layer.transform = transfrom;