提问人:Nick Cartwright 提问时间:12/8/2008 最后编辑:TheNeilNick Cartwright 更新时间:1/31/2021 访问量:110963
如何将透视转换应用于 UIView?
How do I apply a perspective transform to a UIView?
问:
我希望在 UIView 上执行透视转换(例如在 coverflow 中看到)
有谁知道这是否可行?
我已经调查了使用并浏览了所有务实的程序员 Core Animation 播客,但我仍然不清楚如何在 iPhone 上创建这种转换。CALayer
任何帮助、指针或示例代码片段将不胜感激!
答:
只能使用直接应用于 UIView 的 transform 属性的 Core Graphics(仅限 Quartz、2D)转换。要在 coverflow 中获得效果,您必须使用 CATransform3D,它应用于 3D 空间,因此可以为您提供所需的透视图。您只能将 CATransform3D 应用于图层,而不能应用于视图,因此您必须为此切换到图层。
查看 Xcode 附带的“CovertFlow”示例。它仅适用于 mac(即不适用于 iPhone),但很多概念都很好地转移了。
评论
正如 Ben 所说,您需要使用该层,使用 a 来执行 .如此处所述,让透视工作的诀窍是直接访问 (m34) 的矩阵之一。矩阵数学从来都不是我的专长,所以我无法确切解释为什么它有效,但它确实如此。您需要将初始变换的此值设置为负分数,然后将图层旋转变换应用于该值。您还应该能够执行以下操作:UIView's
CATransform3D
layer's
rotation
cells
CATransform3D
Objective-C语言
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
}
它从头开始为每次旋转重建图层变换。
可以在此处找到一个完整的示例(带有代码),其中我根据 Bill Dudney 的示例在几个 上实现了基于触摸的旋转和缩放。该程序的最新版本,在页面的最底部,实现了这种透视操作。代码应该相当简单易读。CALayers
您在响应中引用的是应用于 .如果您没有任何子图层,请不要担心。我在示例中使用 sublayerTransform,仅仅是因为我正在旋转的一层中包含两个。sublayerTransform
UIView's
CALayer
CALayers
评论
您可以使用 iCarousel SDK 获得准确的轮播效果。
您可以使用奇妙且免费的 iCarousel 库在 iOS 上获得即时的 Cover Flow 效果。你可以从 https://github.com/nicklockwood/iCarousel 下载它,并通过添加桥接头(它是用 Objective-C 编写的)相当容易地将其放入你的 Xcode 项目中。
如果您之前没有将 Objective-C 代码添加到 Swift 项目,请按照以下步骤操作:
- 下载 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
}
斯威夫特 5.0
func makeTransform(horizontalDegree: CGFloat, verticalDegree: CGFloat, maxVertical: CGFloat,rotateDegree: CGFloat, maxHorizontal: CGFloat) -> CATransform3D {
var transform = CATransform3DIdentity
transform.m34 = 1 / -500
let xAnchor = (horizontalDegree / (2 * maxHorizontal)) + 0.5
let yAnchor = (verticalDegree / (-2 * maxVertical)) + 0.5
let anchor = CGPoint(x: xAnchor, y: yAnchor)
setAnchorPoint(anchorPoint: anchor, forView: self.imgView)
let hDegree = (CGFloat(horizontalDegree) * .pi) / 180
let vDegree = (CGFloat(verticalDegree) * .pi) / 180
let rDegree = (CGFloat(rotateDegree) * .pi) / 180
transform = CATransform3DRotate(transform, vDegree , 1, 0, 0)
transform = CATransform3DRotate(transform, hDegree , 0, 1, 0)
transform = CATransform3DRotate(transform, rDegree , 0, 0, 1)
return transform
}
func setAnchorPoint(anchorPoint: CGPoint, forView view: UIView) {
var newPoint = CGPoint(x: view.bounds.size.width * anchorPoint.x, y: view.bounds.size.height * anchorPoint.y)
var oldPoint = CGPoint(x: view.bounds.size.width * view.layer.anchorPoint.x, y: view.bounds.size.height * view.layer.anchorPoint.y)
newPoint = newPoint.applying(view.transform)
oldPoint = oldPoint.applying(view.transform)
var position = view.layer.position
position.x -= oldPoint.x
position.x += newPoint.x
position.y -= oldPoint.y
position.y += newPoint.y
print("Anchor: \(anchorPoint)")
view.layer.position = position
view.layer.anchorPoint = anchorPoint
}
您只需要使用您的学位调用该函数。例如:
var transform = makeTransform(horizontalDegree: 20.0 , verticalDegree: 25.0, maxVertical: 25, rotateDegree: 20, maxHorizontal: 25)
imgView.layer.transform = transform
评论