Frage

Ich versuche, ein einfaches iPhone-App zu erstellen, das zeigt ein Bild mit einer Reflexion unter, und ich möchte das Bild um die X-Achse drehen, Core Animation verwenden.

Ich habe angefangen, ein neues iPhone-App, indem mit der „View-basierter Anwendung“ Vorlage. Ich habe eine „Picture.jpg“ Image-Datei, und dann habe ich dies die View-Controller:

- (void)awakeFromNib {
    CGFloat zDistance = 1500.0f;

    // Create perspective transformation
    CATransform3D transform = CATransform3DIdentity;
    transform.m34 = 1.0f / -zDistance;

    // Create perspective transform for reflected layer
    CATransform3D reflectedTransform = CATransform3DMakeRotation(M_PI, 1.0f, 0.0f, 0.0f);
    reflectedTransform.m34 = 1.0f / -zDistance;

    // Create spinning picture
    CALayer *spinningLayer = [CALayer layer];
    spinningLayer.frame = CGRectMake(60.0f, 60.0f, 200.0f, 300.0f);
    spinningLayer.contents = (id)[UIImage imageNamed:@"Picture.jpg"].CGImage;
    spinningLayer.transform = transform;    

    // Create reflection of spinning picture
    CALayer *reflectionLayer = [CALayer layer];
    reflectionLayer.frame = CGRectMake(60.0f, 360.0f, 200.0f, 300.0f);
    reflectionLayer.contents = (id)[UIImage imageNamed:@"Picture.jpg"].CGImage;
    reflectionLayer.opacity = 0.4f;
    reflectionLayer.transform = reflectedTransform;

    // Add layers to the root layer
    [self.view.layer addSublayer:spinningLayer];
    [self.view.layer insertSublayer:reflectionLayer below:spinningLayer];

    // Spin the layers
    CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform.rotation.y"];
    anim.fromValue = [NSNumber numberWithFloat:0.0f];
    anim.toValue = [NSNumber numberWithFloat:(2 * M_PI)];
    anim.duration = 3.0f;
    anim.repeatCount = 1e100f;
    [spinningLayer addAnimation:anim forKey:@"anim"];
    [reflectionLayer addAnimation:anim forKey:@"anim"];
}

Das fast funktioniert. Das Problem ist, dass das Drehen des Hauptbildes und der Reflexion nicht perfekt synchronisiert. Es ist ganz in der Nähe perfekt, aber die Ränder des unteren Randes des Bildes und von oben auf der Reflexion voneinander entfernt sind einige Pixel. Sie erscheinen um ein paar Grad zu unterscheiden.

Auf der linken Seite des Bildschirms erscheint die Reflexion zu sein „ahead“ des Bildes, und auf der rechten Seite, die Reflexion hinter dem Bild. Mit anderen Worten, es sieht aus wie die unteren Ecken des oberen Bildes auf den Bildschirm gedrückt wird, während die oberen Ecken der Reflexion in Richtung auf den Betrachter gezogen. Dies gilt sowohl, wenn an der Vorder- und an der Rückseite der Bilder an, als sie sich drehen.

Wenn ich zDistance erhöhen, ist der Effekt weniger bemerkbar. Wenn ich die Perspektive Transformationen insgesamt durch Verlassen transform.m34 gleich Null für beiden Schichten zu eliminieren, dann das Bild und Spiegelbild Look perfekt synchronisiert werden. Also ich glaube nicht, das Problem zu Zeitsynchronisierungsproblemen in Zusammenhang steht.

Ich vermute, meine Perspektive Transformationen etwas fehlt, aber ich bin nicht sicher, wie um zu bestimmen, was falsch ist. Ich glaube, ich bin im Grunde die gleiche Transformation in diesem Zusammenhang Stack Overflow Frage beschrieben tun.

Kann jemand helfen?

War es hilfreich?

Lösung

ich glaube, ich eine Antwort auf meine Frage gefunden haben. In meinem ursprünglichen Code, habe ich die Reflexion durch sie unter dem Bild platzieren und die Flip und Perspektive anwenden. Der richtige Weg, es zu tun scheint die Reflexion an der gleichen Position wie das Bild zu platzieren sind, gelten Transformationen Translation und Rotation sie an die richtige Stelle zu bekommen, und dann die Perspektive Transformation anzuwenden.

Wenn die Spin Animieren, ist es notwendig, die Reflexion in der entgegengesetzten Richtung des Bildes der Animation zu drehen.

So, hier der Code, das funktioniert:

- (void)awakeFromNib {
    CGFloat zDistance = 1500.0f;

    // Create perspective transformation
    CATransform3D transform = CATransform3DIdentity;
    transform.m34 = 1.0f / -zDistance;

    // Create perspective transform for reflected layer
    CATransform3D reflectedTransform = CATransform3DMakeTranslation(0.0f, 300.0f, 0.0f);
    reflectedTransform = CATransform3DRotate(reflectedTransform, M_PI, 1.0f, 0.0f, 0.0f);
    reflectedTransform.m34 = 1.0f / -zDistance;

    // Create spinning picture
    CALayer *spinningLayer = [CALayer layer];
    spinningLayer.frame = CGRectMake(60.0f, 60.0f, 200.0f, 300.0f);
    spinningLayer.contents = (id)[UIImage imageNamed:@"Picture.jpg"].CGImage;
    spinningLayer.transform = transform;    

    // Create reflection of spinning picture
    CALayer *reflectionLayer = [CALayer layer];
    reflectionLayer.frame = CGRectMake(60.0f, 60.0f, 200.0f, 300.0f);
    reflectionLayer.contents = (id)[UIImage imageNamed:@"Picture.jpg"].CGImage;
    reflectionLayer.opacity = 0.4f;
    reflectionLayer.transform = reflectedTransform;

    // Add layers to the root layer
    [self.view.layer addSublayer:spinningLayer];
    [self.view.layer insertSublayer:reflectionLayer below:spinningLayer];

    // Spin the layers
    CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform.rotation.y"];
    anim.fromValue = [NSNumber numberWithFloat:0.0f];
    anim.toValue = [NSNumber numberWithFloat:(2 * M_PI)];
    anim.duration = 3.0f;
    anim.repeatCount = 1e100f;
    [spinningLayer addAnimation:anim forKey:@"anim"];

    CABasicAnimation *reflectAnim = [CABasicAnimation animationWithKeyPath:@"transform.rotation.y"];
    reflectAnim.fromValue = [NSNumber numberWithFloat:0.0f];
    reflectAnim.toValue = [NSNumber numberWithFloat:(-2 * M_PI)];
    reflectAnim.duration = 3.0f;
    reflectAnim.repeatCount = 1e100f;
    [reflectionLayer addAnimation:reflectAnim forKey:@"reflectAnim"];
}

Ich bin mir nicht ganz sicher, warum das funktioniert. Es macht intuitiv Sinn für mich, dass die Reflexion an der gleichen Position wie das Original platzieren und dann verwandeln sie irgendwie die beiden Bilder in den gleichen „Transformationsraum“ bringen, aber ich würde es begrüßen, wenn jemand die Mathematik dahinter erklären könnte.

Das vollständige Projekt ist auf GitHub verfügbar: https://github.com/kristopherjohnson/perspectivetest

Andere Tipps

Sie können mit einem CAAnimationGroup Objekt zwei Animationen auf dem gleichen Zeitraum laufen. Das sollte von allen Synchronisierungsprobleme kümmern.

EDIT: entfernt dummer Code

.
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top