我正在尝试创建一个简单的 iPhone 应用程序,该应用程序显示下面带有反射的图片,并且我想使用 Core Animation 绕 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 两个层均为零,则图像和反射看起来完美同步。所以我不认为这个问题与时间同步问题有关。

我怀疑我的视角转换遗漏了一些东西,但我不确定如何确定哪里出了问题。我想我基本上是在做与中描述的相同的转换 这个相关的堆栈溢出问题.

有人可以帮忙吗?

有帮助吗?

解决方案

我想我可能已经找到了答案,我的问题。在我的原代码中,我通过将其放置在图像的下方,以及将所述翻转和透视产生的反射。做正确的做法似乎是放置在反射相同的位置的图片,应用平移和旋转变换来得到它的正确的地方,然后应用透视变换。

当动画自旋,有必要以旋转反射在照片动画的方向相反。

所以,这里的代码如下:

- (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

其他提示

您可以使用 CAAnimationGroup 对象在同一时间空间上运行两个动画。这应该可以解决任何同步问题。

编辑: 删除了愚蠢的代码。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top