문제

아래에 반사가있는 사진을 표시하는 간단한 iPhone 앱을 만들려고 노력하고 있으며 코어 애니메이션을 사용하여 X 축 주위에서 그림을 회전하려고합니다.

"보기 기반 응용 프로그램"템플릿을 사용하여 새로운 iPhone 앱을 만들기 시작했습니다. "picture.jpg"이미지 파일을 추가 한 다음 view 컨트롤러에 추가했습니다.

- (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 두 레이어 모두에 대해 0과 같으면 그림과 반사는 완벽하게 동기화되는 것으로 보입니다. 따라서 문제가 시간 동기화 문제와 관련이 있다고 생각하지 않습니다.

내 관점 변환이 무언가를 놓치고 있다고 생각하지만, 무엇이 잘못되었는지 결정하는 방법을 잘 모르겠습니다. 기본적으로 묘사 된 동일한 변형을하고 있다고 생각합니다. 이 관련 스택 오버플로 질문.

누군가 도울 수 있습니까?

도움이 되었습니까?

해결책

내 질문에 대한 답을 찾았을 것 같아요. 원래 코드에서는 그림 아래에 배치하고 플립과 관점을 적용하여 반사를 만들었습니다. 올바른 방법은 반사를 그림과 같은 위치에 놓고 번역 및 회전 변환을 적절한 위치로 가져오고 관점 변환을 적용하는 것 같습니다.

스핀을 애니메이션 할 때는 반사를 그림 애니메이션의 반대 방향으로 회전시켜야합니다.

따라서 다음은 작동하는 코드입니다.

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

왜 이것이 왜 작동하는지 잘 모르겠습니다. 반사를 원본과 같은 위치에 놓고 그것을 변환하면 두 이미지를 동일한 "변환 공간"으로 바꾸는 것이 직관적이지만, 누군가 가이 뒤에있는 수학을 설명 할 수 있다면 감사합니다.

전체 프로젝트는 Github에서 사용할 수 있습니다. https://github.com/kristopherjohnson/perspectiveTest

다른 팁

당신은 a를 사용할 수 있습니다 CAAnimationGroup 동일한 시간 공간에서 두 개의 애니메이션을 실행하려면 개체합니다. 동기화 문제를 처리해야합니다.

편집하다: 바보 같은 코드를 제거했습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top