فشل محاولة استخدام تحويلات المنظور في الرسوم المتحركة الأساسية

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

سؤال

أحاول إنشاء تطبيق iPhone بسيط يعرض صورة مع انعكاس أسفلها، وأريد تدوير الصورة حول المحور X، باستخدام الرسوم المتحركة الأساسية.

لقد بدأت بإنشاء تطبيق iPhone جديد باستخدام قالب "التطبيق القائم على العرض".أضفت ملف صورة "Picture.jpg"، ثم أضفت هذا إلى وحدة التحكم في العرض:

- (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"];
}

هذا بالكاد يعمل.تكمن المشكلة في أن دوران الصورة الرئيسية وانعكاسها غير متزامنين تمامًا.إنه قريب جدًا من الكمال، لكن حواف الجزء السفلي من الصورة والجزء العلوي من الانعكاس متباعدة ببضعة بكسلات.يبدو أنها تختلف ببضع درجات.

على الجانب الأيسر من الشاشة، يبدو الانعكاس "أمام" الصورة، وعلى الجانب الأيمن، الانعكاس خلف الصورة.بمعنى آخر، يبدو أن الزوايا السفلية للصورة العلوية يتم دفعها نحو الشاشة، بينما يتم سحب الزوايا العلوية من الانعكاس نحو المشاهد.وينطبق هذا على كل من النظر إلى الجزء الأمامي والخلفي من الصور أثناء دورانها.

إذا قمت بزيادة zDistance, ، التأثير أقل وضوحًا.إذا قمت بإزالة تحولات المنظور تمامًا عن طريق المغادرة transform.m34 يساوي صفرًا لكلتا الطبقتين، فتبدو الصورة والانعكاس متزامنين تمامًا.لذلك لا أعتقد أن المشكلة مرتبطة بقضايا مزامنة الوقت.

أظن أن تحولات وجهة نظري تفتقد شيئًا ما، لكنني لست متأكدًا من كيفية تحديد الخطأ.أعتقد أنني أقوم بنفس التحول الموضح في هذا السؤال ذو الصلة بـ Stack Overflow.

يمكن للشخص أن يساعد؟

هل كانت مفيدة؟

المحلول

وأعتقد أنني قد وجدت جوابا على سؤالي. في قانون بلدي الأصلي، أنا خلق انعكاس عن طريق وضعها تحت الصورة، وتطبيق الوجه والمنظور. الطريقة الصحيحة للقيام بذلك ويبدو أن وضع انعكاس في نفس الموقف الصورة، وتطبيق الترجمة وتناوب التحويلات للحصول عليه إلى المكان الصحيح، ومن ثم تطبيق التحول المنظور.

عند موحية زيادة ونقصان، فمن الضروري أن تدور انعكاس في الاتجاه المعاكس للرسوم المتحركة والصورة.

وهكذا، رمز هنا أن الأعمال:

- (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"];
}

وأنا لست متأكدا بالضبط لماذا هذه الأعمال. فمن المنطقي بديهية بالنسبة لي أن وضع انعكاس في نفس الموقف الأصلي ومن ثم تحويلها يضع حد ما الصورتين في نفس "الفضاء التحول"، ولكن أود أن نقدر ذلك اذا كان شخص ما يمكن أن يفسر الرياضيات وراء ذلك.

وهذا المشروع الكامل متوفر في جيثب: https://github.com/kristopherjohnson/perspectivetest

نصائح أخرى

يمكنك استخدام أ CAAnimationGroup كائن لتشغيل حركتين في نفس المساحة الزمنية.يجب أن يعتني بأي مشكلات في المزامنة.

يحرر: إزالة رمز سخيف.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top