我们如何在 3D 空间中同时旋转 2 个 UIView 平面

Posted

技术标签:

【中文标题】我们如何在 3D 空间中同时旋转 2 个 UIView 平面【英文标题】:How do we rotate 2 UIView planes simultaneously in 3D space 【发布时间】:2014-04-21 15:34:51 【问题描述】:

由于项目限制,我正在尝试使用 UIView 而不是 CALayer 创建“翻页效果”。这需要将 1 个 UIView 翻转 180 度并基本上将其“粘贴”到另一个 UIView 的背面。然后通过在 3D 空间中旋转超级视图来同时旋转两个 UIView。

我正在尝试移植 AFKPageFlipper's "initFlip" method 以使用 UIView 而不是 UIImage。

以下是我尝试移植它的 sn-p。初始页面翻转有效,但代码中的“前层”似乎没有出现。好像我无法看到页面的后端。当我翻页时,动画最初是正确的(背面层很好),但是页面的另一侧(正面层),我看到了第一页的倒置视图(backLayer)。

任何帮助都会很棒!

flipAnimationLayer = [[UIView alloc] init];

flipAnimationLayer.layer.anchorPoint = CGPointMake(1.0, 0.5);
flipAnimationLayer.layer.frame = rect;

[self addSubview:flipAnimationLayer];

UIView *backLayer;
UIView *frontLayer;
if (flipDirection == AFKPageFlipperDirectionRight)

    backLayer = currentViewSnap2;
    backLayer.layer.contentsGravity = kCAGravityLeft;

    frontLayer = nextViewSnap2;
    frontLayer.layer.contentsGravity = kCAGravityRight;

else

    backLayer = nextViewSnap2;
    backLayer.layer.contentsGravity = kCAGravityLeft;

    frontLayer= currentViewSnap2;
    frontLayer.layer.contentsGravity = kCAGravityRight;



backLayer.frame = flipAnimationLayer.bounds;
backLayer.layer.doubleSided = NO;
backLayer.clipsToBounds = YES;

[flipAnimationLayer addSubview:backLayer];


frontLayer.frame = flipAnimationLayer.bounds;
frontLayer.layer.doubleSided = NO;
frontLayer.clipsToBounds = YES;
frontLayer.layer.transform = CATransform3DMakeRotation(M_PI, 0, 1.0, 0);

[flipAnimationLayer addSubview:frontLayer];

if (flipDirection == AFKPageFlipperDirectionRight)

    CATransform3D transform = CATransform3DMakeRotation(0.0, 0.0, 1.0, 0.0);
    transform.m34 = 1.0f / 2500.0f;

    flipAnimationLayer.layer.transform = transform;

    currentAngle = startFlipAngle = 0;
    endFlipAngle = -M_PI;
 else



    CATransform3D transform = CATransform3DMakeRotation(-M_PI / 1.1, 0.0, 1.0, 0.0);
    transform.m34 = 1.0f / 2500.0f;

    flipAnimationLayer.layer.transform = transform;

    currentAngle = startFlipAngle = -M_PI;
    endFlipAngle = 0;

【问题讨论】:

【参考方案1】:

您的代码正在旋转图层,而不是视图。没关系。

我不希望您发布的代码能够制作动画,因为图层的背景视图不执行隐式动画,您可以使用 CABasicAnimation 使其动画。或者,您可以为前视图和后视图创建​​图层并将它们附加为视图图层的子图层。如果你这样做,那么在图层上操作变换将使用隐式动画。

按照您的描述,我创建自己的字体到后翻页所做的就是伪造它。

我分两步制作动画:首先从 0 度(平面)到 90 度(图层变得不可见)。在那一刻,我隐藏了第一层并使第二层可见,反之旋转 90 度,然后然后将另一层旋转回零。这会产生与显示旋转背面相同的视觉效果。

如果您使用隐式图层动画来执行此操作,您需要将变换的更改放在 CATransaction 块中并将动画时间设置为线性,或者在前半部分使用缓入,在前半部分使用缓出下半场。这是因为动画默认是缓入缓出时序,第一个90度的动画最后会变慢,然后第二个90度的动画会缓入。

【讨论】:

谢谢邓肯!! 90 度互换效果很好!! :D 所以为了更好地理解。不可能将 UIView 翻转 180 度以表示“后页”并基本上将其“粘贴”在“首页”UIView 后面?我知道这种方法对于 Layers 是可行的,但对于 UIViews 似乎是不可能的......再次感谢! 据我所知,将视图或图层旋转 180 度是不可能的。无论如何,您都必须伪造它。 有趣。我在上面发布的 AFKPageFlipper 链接完美运行,似乎通过图层“旋转 180 度/M_PI 弧度”。我可能误解了代码,但从这一行来看,它看起来像是 180 度翻转:frontLayer.transform = CATransform3DMakeRotation(M_PI, 0, 1.0, 0);

以上是关于我们如何在 3D 空间中同时旋转 2 个 UIView 平面的主要内容,如果未能解决你的问题,请参考以下文章

如何在 3D 空间中旋转矢量? P5.js

在 3d 空间中移动一个点

Canvas实现3D效果-可旋转的立方体

3d变换基础:平移旋转缩放(仿射变换)详解——公式推导

如何css制作3d旋转立方体效果?

Stone教程:如何选中平移旋转和缩放实体