如何将透视变换应用于UIView?


199

我正在寻找对UIView执行透视转换(如Coverflow中所示)

有人知道这是否可能吗?

我调查了使用 CALayer所有实用的程序员Core Animation播客的并进行了遍历,但是我仍然不清楚如何在iPhone上创建这种转换。

任何帮助,指针或示例代码片段都将不胜感激!


我不确定这是否适合您,但是当我制作动画时,我发现m14更适合我:仅供参考:)
b123400 2010年

谢谢!-您给哪个值?
尼克·卡特赖特

1
通过设置m14,您实际上实际上在使X轴上的视锥变成怪异的。数学是完全有效的,但在一般情况下会使情况有些混乱。
蓬松的

可以在这篇出色的文章中找到有关CALayer 3D转换和透视的非常非常好的文章,包括对m34领域的详尽解释:core-animation-3d-model
Markus

Answers:


329

正如Ben所说,您需要使用UIView'sCATransform3D来执行,以处理图层layer's rotation。如此处所述,获取透视工作的技巧是直接访问(m34)的矩阵cells之一CATransform3D。矩阵数学从来都不是我的事,因此我无法确切解释为什么这样做,但确实如此。您需要为初始转换将此值设置为负分数,然后将图层旋转转换应用于该值。您还应该能够执行以下操作:

物镜

UIView *myView = [[self subviews] objectAtIndex:0];
CALayer *layer = myView.layer;
CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity;
rotationAndPerspectiveTransform.m34 = 1.0 / -500;
rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, 45.0f * M_PI / 180.0f, 0.0f, 1.0f, 0.0f);
layer.transform = rotationAndPerspectiveTransform;

斯威夫特5.0

if let myView = self.subviews.first {
    let layer = myView.layer
    var rotationAndPerspectiveTransform = CATransform3DIdentity
    rotationAndPerspectiveTransform.m34 = 1.0 / -500
    rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, 45.0 * .pi / 180.0, 0.0, 1.0, 0.0)
    layer.transform = rotationAndPerspectiveTransform
}

每次旋转都会从头开始重建图层变换。

此处可以找到完整的示例(包含代码),其中我CALayers基于Bill Dudney的示例在几个示例上实现了基于触摸的旋转和缩放。该程序的最新版本位于页面的最底部,实现了这种透视操作。该代码应相当简单易读。

sublayerTransform你指的是你的反应是一个转换,应用到你的子层UIView's CALayer。如果您没有任何子层,请不必担心。我在示例中使用sublayerTransform只是因为CALayers我旋转的一层中包含两个。


1
谢谢布拉德-你是明星。PS:对不起,您的回答太迟了!缺口。
尼克·卡特赖特

这对我来说效果很好,除了我似乎失去了一半的图像(沿垂直方向分割)-有时是LHS,有时是RHS。
iPadDeveloper2011 2011年

18
@ iPadDeveloper2011-奇怪的是,当同一平面上存在另一个不透明视图或图层时,您正在尝试旋转视图或图层。远离屏幕投影的视图或图层的一半将位于该另一视图下方,因此被隐藏。您可以重新排序视图层次结构以防止这种情况,或者使用zPosition属性将前景视图移到将其切除的视图上方足够高的位置。
布拉德·拉尔森

26
仅供参考,m34单元会影响透视变换的原因是矩阵中的单元会影响世界空间Z值如何映射到剪辑空间W值(用于透视投影)。阅读有关均匀变换矩阵的更多信息。
蓬松的

2
@uerceg-您想将其作为一个单独的问题提出,最好是带有说明正在发生的事情和想要发生的事情的图像。
布拉德·拉尔森

7

您只能使用直接应用于UIView的transform属性的Core Graphics(仅限于石英,2D)变换。要获得Coverflow的效果,您必须使用在3D空间中应用的CATransform3D,因此可以为您提供所需的透视图。您只能将CATransform3D应用于图层,而不能应用于视图,因此您将不得不切换到图层。

查看Xcode随附的“ CovertFlow”示例。它仅用于Mac(即,不适用于iPhone),但是许多概念都可以很好地传递。


我正在/ Developer / Examples中寻找该Coverflow示例,但没有成功,您在哪里可以找到它?
亚历克斯

它实际上是“ CovertFlow”,位于/ Developer / Examples / Quartz / Core Animation /中
Ben Gottlieb,

3

为了增加布拉德的答案并提供一个具体的例子,我在另一篇类似主题的文章中借用了自己的答案。在我的回答中,我创建了一个简单的Swift游乐场,您可以下载和使用它,并在其中演示如何创建具有简单图层层次结构的UIView的透视效果,并展示使用transform和之间的不同结果sublayerTransform。看看这个。

以下是帖子中的一些图片:

.sublayerTransform选项

.transform选项


代码应以文本形式发布。很难读取图像中的代码。另外,图片中的代码无法引用,复制或搜索。
rmaddy

@rmaddy,我的答案在Bitbucket链接中有可用的代码。
HuaTham

链接随着时间变坏。始终最好将重要的代码作为文本直接粘贴到答案中。
rmaddy

-1

您可以使用iCarousel SDK获得准确的Carousel效果。

您可以使用出色的免费iCarousel库在iOS上即时获得Cover Flow效果。您可以从https://github.com/nicklockwood/iCarousel下载它,并通过添加桥接标头(用Objective-C编写)相当容易地将其放入Xcode项目。

如果您之前没有向Swift项目添加Objective-C代码,请按照以下步骤操作:

  • 下载iCarousel并解压缩
  • 进入解压缩的文件夹,打开其iCarousel子文件夹,然后选择iCarousel.h和iCarousel.m并将它们拖动到项目导航中-这是Xcode的左窗格。在Info.plist的正下方即可。
  • 选中“如果需要复制项目”,然后单击“完成”。
  • Xcode将提示您“是否要配置Objective-C桥接标头?”消息。单击“创建桥接头”,您应该在项目中看到一个名为YourProjectName-Bridging-Header.h的新文件。
  • 将此行添加到文件中:#import“ iCarousel.h”
  • 将iCarousel添加到项目中后,就可以开始使用它了。
  • 确保您同时遵守iCarouselDelegate和iCarouselDataSource协议。

Swift 3示例代码:

    override func viewDidLoad() {
      super.viewDidLoad()
      let carousel = iCarousel(frame: CGRect(x: 0, y: 0, width: 300, height: 200))
      carousel.dataSource = self
      carousel.type = .coverFlow
      view.addSubview(carousel) 
    }

   func numberOfItems(in carousel: iCarousel) -> Int {
        return 10
    }

    func carousel(_ carousel: iCarousel, viewForItemAt index: Int, reusing view: UIView?) -> UIView {
        let imageView: UIImageView

        if view != nil {
            imageView = view as! UIImageView
        } else {
            imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 128, height: 128))
        }

        imageView.image = UIImage(named: "example")

        return imageView
    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.