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

Ios 如何将透视变换应用于UIView?,ios,cocoa-touch,uiview,core-animation,calayer,Ios,Cocoa Touch,Uiview,Core Animation,Calayer,我希望在UIView上执行透视变换,如coverflow中所示 有人知道这是否可能吗 我已经研究过使用CALayer,并浏览了所有实用的程序员核心动画播客,但我仍然不清楚如何在iPhone上创建这种转换 任何帮助、指针或示例代码片段都将不胜感激 只能使用直接应用于UIView变换属性的仅二维核心图形石英变换。要在coverflow中获得效果,您必须使用CATTransform3D,它应用于三维空间,因此可以为您提供所需的透视图。只能将CATTransferM3D应用于图层,而不能应用于视图,因此

我希望在UIView上执行透视变换,如coverflow中所示

有人知道这是否可能吗

我已经研究过使用CALayer,并浏览了所有实用的程序员核心动画播客,但我仍然不清楚如何在iPhone上创建这种转换


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

只能使用直接应用于UIView变换属性的仅二维核心图形石英变换。要在coverflow中获得效果,您必须使用CATTransform3D,它应用于三维空间,因此可以为您提供所需的透视图。只能将CATTransferM3D应用于图层,而不能应用于视图,因此必须切换到图层


查看Xcode附带的CovertFlow示例。这是只适用于mac的ie,不适用于iPhone,但很多概念都能很好地传递。

正如Ben所说,您需要使用UIView的层,使用CATTransform3D来执行层的旋转。让透视图工作的诀窍是直接访问CATTransferM3D m34的一个矩阵单元。矩阵数学从来都不是我喜欢的东西,所以我不能确切地解释为什么它会起作用,但它确实起作用。对于初始变换,需要将该值设置为负分数,然后将层旋转变换应用于该值。您还应该能够执行以下操作:

目标-C

UIView*myView=[[self subviews]objectAtIndex:0]; CALayer*layer=myView.layer; CATTransferM3D旋转和透视变换=CATTransferM3D实体; 旋转和透视变换.m34=1.0/-500; 旋转和透视变换=CATTransferorM3dRotate旋转和透视变换,45.0f*MμPI/180.0f,0.0f,1.0f,0.0f; layer.transform=旋转和透视变换; Swift 5.0

如果让myView=self.subviews.first{ let layer=myView.layer var rotationAndPerspectiveTransform=CATTransferorM3DidEntity 旋转和透视变换.m34=1.0/-500 rotationAndPerspectiveTransform=CATTransformorM3dRotationandPerspectiveTransform,45.0*.pi/180.0,0.0,1.0,0.0 layer.transform=旋转和透视变换 } 这将为每次旋转从头开始重建层变换

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


您在响应中提到的sublayerTransform是应用于UIView CALayer的子层的转换。如果没有任何子层,请不要担心。我在示例中使用sublayerTransform只是因为我正在旋转的一个层中包含两个Calayer。

您可以使用iCarousel SDK获得精确的旋转效果

通过使用神奇的免费iCarousel库,您可以在iOS上获得即时封面效果。通过添加一个用Objective-C编写的桥接头,您可以很容易地从Xcode项目下载它并将其放到Xcode项目中

如果您以前没有将Objective-C代码添加到Swift项目中,请执行以下步骤:

下载iCarousel并解压缩它 进入您解压缩的文件夹,打开其iCarousel子文件夹,然后选择iCarousel.h和iCarousel.m并将它们拖到项目导航中–这是Xcode中的左窗格。就在Info.plist下面就可以了。 如果需要,请选中“复制项目”,然后单击“完成”。 Xcode将提示您是否要配置Objective-C桥接头?单击创建桥接标头 您应该在项目中看到一个新文件,名为YourProjectName bridgeing Header.h。 将此行添加到文件:import iCarousel.h 一旦你将iCarousel添加到你的项目中,你就可以开始使用它了。 确保您同时遵守ICARouseldLegate和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
    }
Swift 5.0

您只需要使用您的学位调用函数。例如:

var transform = makeTransform(horizontalDegree: 20.0 , verticalDegree: 25.0, maxVertical: 25, rotateDegree: 20, maxHorizontal: 25)
imgView.layer.transform = transform

我正在/Developer/Examples中寻找这个coverflow示例,但没有成功,你在哪里可以找到它?它实际上是CovertFlow,它在/Developer/Examples/Quartz/Core Animation/Thank Brad中-你是个明星。PS:很抱歉,你的回答太晚了!尼克。这对我来说效果很好,只是我似乎在垂直分割上丢失了一半的图像,有时是LHS,有时是RHS。@iPadDeveloper2011-很可能,当同一平面上有另一个不透明的视图或图层时,您正试图旋转一个视图或图层。投影到屏幕之外的视图或图层的一半将位于另一个视图的下方,因此被隐藏。您可以重新排列视图层次结构以防止出现这种情况,也可以使用zPosition属性将前景视图移动到足够高的位置,使其高于打开的视图
e这就切断了它。仅供参考,m34单元格影响透视变换的原因是矩阵中的单元格影响世界空间Z值映射到用于透视投影的剪辑空间W值的方式。阅读同质变换矩阵以了解更多信息。@uerceg-你会想作为一个单独的问题来问这个问题,最好是用图像来说明正在发生的事情和你想要发生的事情。我不确定这是否适合u,但当我制作动画时,我发现m14更适合我,仅供参考:谢谢你给出了哪些值?通过设置m14,你实际上在X轴上扭曲视锥体。数学是完全正确的,但在一般情况下它会让事情变得混乱。关于CALayer 3D变换和透视的一篇非常非常好的文章,包括对m34字段的透彻解释,可以在这篇优秀的文章中找到:
var transform = makeTransform(horizontalDegree: 20.0 , verticalDegree: 25.0, maxVertical: 25, rotateDegree: 20, maxHorizontal: 25)
imgView.layer.transform = transform