4

我试图创建一个 CATransform3D,但弄错了。以下代码使用键值执行我想要的操作:

[_transitionLayer setValue:[NSNumber numberWithFloat:metrics.translationPointsX] 
    forKeyPath:@"sublayerTransform.translation.x"];
[_transitionLayer setValue:[NSNumber numberWithFloat:metrics.radians] 
    forKeyPath:@"sublayerTransform.rotation.y"];
[_transitionLayer setValue:[NSNumber numberWithFloat:metrics.translationPointsZ] 
    forKeyPath:@"sublayerTransform.translation.z"];

正确的

以下是我尝试设置 CATransform3D 的方法:

subLayerTransform.m34 = -0.000555;
CATransform3D subLayerTransform = CATransform3DMakeTranslation(0, 0, 0);
subLayerTransform = 
    CATransform3DTranslate(subLayerTransform, metrics.translationPointsX, 0, 0);
subLayerTransform = 
    CATransform3DRotate(subLayerTransform, metrics.radians, 0, 1, 0);
subLayerTransform = 
    CATransform3DTranslate(subLayerTransform, 0, 0, metrics.translationPointsZ);

错误的

如何使用 key-paths 创建匹配的转换?

4

1 回答 1

6

查看您的两个屏幕截图,并假设您要获得旋转立方体效果,并且这两个屏幕截图在动画中的时间略有不同,看起来顶部的有透视图,而底部的没有。

解决这个问题很简单,只需编辑变换的 .m34 值,通常为一个较小的值,例如 1/500。这里有一篇很好的文章。

完成后,您需要在旋转之前应用平移步骤,如下所示:

CATransform3D subLayerTransform = CATransform3DMakeTranslation(0, 0, 0);
subLayerTransform.m34 = -0.000555;
subLayerTransform = CATransform3DTranslate(subLayerTransform, _currentMetrics.translationPointsX, 0, _currentMetrics.translationPointsZ);
subLayerTransform = CATransform3DRotate(subLayerTransform, _currentMetrics.radians, 0, 1, 0);

我做过类似的事情,但使用容器视图控制器从一个切换到下一个。在评论您的代码时,我以为我使用了 z 锚点,但事实证明我没有。这是我用来从一个视图控制器转换到另一个视图控制器的代码,就好像你在旋转一个立方体一样。它可能很有趣。这只是从更大的方法中提取的,希望我没有错过任何重要的东西。

CGRect newFrame = self.containerView.bounds;
UIView *outgoingView = _currentViewController.view;
UIView *incomingView = currentViewController.view;

incomingView.frame = newFrame;

[CATransaction begin];
[CATransaction setDisableActions:YES];

CATransform3D parent = CATransform3DIdentity;
parent.m34 = -0.003;
self.containerView.layer.sublayerTransform = parent;

BOOL rightToLeft = (_currentViewController == [self.viewControllers itemBefore:currentViewController]);

CGFloat inTranslateX = incomingView.bounds.size.width;
CGFloat inRotation = M_PI_2;
CGFloat inAnchorX = 0.0;
if (!rightToLeft)
{
    inTranslateX = -inTranslateX;
    inRotation = -inRotation;
    inAnchorX = 1.0;
}


CATransform3D inT = CATransform3DMakeTranslation(inTranslateX, 0.0, 0.0);
inT = CATransform3DRotate(inT, inRotation, 0.0, 1.0, 0.0);
CGRect previousFrame = incomingView.frame;
incomingView.layer.anchorPoint = CGPointMake(inAnchorX, 0.5);
incomingView.frame = previousFrame;
incomingView.layer.transform = inT;
incomingView.hidden = NO;

CGFloat outTranslateX = -outgoingView.bounds.size.width;
CGFloat outRotation = -M_PI_2;
CGFloat outAnchorX = 1.0;
if (!rightToLeft)
{
    outTranslateX = -outTranslateX;
    outRotation = -outRotation;
    outAnchorX = 0.0;
}

CATransform3D outT = CATransform3DMakeTranslation(outTranslateX, 0.0, 0.0);
outT = CATransform3DRotate(outT, outRotation, 0.0, 0.5, 0.0);
CGRect outgoingFrame = outgoingView.frame;
outgoingView.layer.anchorPoint = CGPointMake(outAnchorX, 0.5);
outgoingView.frame = outgoingFrame;
[CATransaction commit];

[self transitionFromViewController:_currentViewController
                  toViewController:currentViewController
                          duration:0.4
                           options:UIViewAnimationCurveEaseInOut
                        animations:^{
                            outgoingView.layer.transform = outT;
                            incomingView.layer.transform = CATransform3DIdentity;
                        }
                        completion:^(BOOL finished) {
                            _currentViewController = currentViewController;
                            outgoingView.layer.transform = CATransform3DIdentity;
                            self.imageView.image = currentViewController.tabBarItem.image;
                            self.viewSelector.userInteractionEnabled = YES;
                        }];

为了试验 3D 变换,我创建了一个小演示应用程序,可让您构建一堆变换并查看效果。它在GitHub上可用,并在此处介绍。

于 2013-05-25T06:51:28.227 回答