将变换添加到 CALayer(平移旋转刻度)

基本

你可以在一个图层上执行许多不同的变换,但基本的变换是

  • 翻译(移动)
  • 规模
  • 回转

StackOverflow 文档

要在 CALayer 上进行变换,可以将图层的 transform 属性设置为 CATransform3D 类型。例如,要翻译图层,你可以执行以下操作:

myLayer.transform = CATransform3DMakeTranslation(20, 30, 0)

Make 这个词在名称中用于创建初始变换:CATransform3D Make Translation。应用的后续变换省略了 Make。例如,请参阅此轮换后跟翻译:

let rotation = CATransform3DMakeRotation(CGFloat(30.0 * M_PI / 180.0), 20, 20, 0)
myLayer.transform = CATransform3DTranslate(rotation, 20, 30, 0)

现在我们已经有了如何进行转换的基础,让我们看看如何做每个转换的一些例子。首先,我将展示如何设置项目,以防你想要使用它。

建立

对于以下示例,我设置了一个单视图应用程序,并在故事板中添加了一个浅蓝色背景的 UIView。我使用以下代码将视图连接到视图控制器:

import UIKit

class ViewController: UIViewController {
    
    var myLayer = CATextLayer()
    @IBOutlet weak var myView: UIView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // setup the sublayer
        addSubLayer()
        
        // do the transform
        transformExample()
    }
    
    func addSubLayer() {
        myLayer.frame = CGRect(x: 0, y: 0, width: 100, height: 40)
        myLayer.backgroundColor = UIColor.blueColor().CGColor
        myLayer.string = "Hello"
        myView.layer.addSublayer(myLayer)
    }
    
    //******** Replace this function with the examples below ********

    func transformExample() {
        
        // add transform code here ...
        
        
    }

} 

有许多不同种类的 CALayer ,但我选择使用 CATextLayer,以便视觉上的变形更清晰。

翻译

平移变换移动图层。基本语法是

CATransform3DMakeTranslation(tx: CGFloat, ty: CGFloat, tz: CGFloat)

其中 tx 是 x 坐标的变化,ty 是 y 的变化,tz 是 z 的变化。

StackOverflow 文档

在 iOS 中,坐标系的原点位于左上角,因此如果我们想将图层向右移动 90 点并向下移动 50 点,我们将执行以下操作:

myLayer.transform = CATransform3DMakeTranslation(90, 50, 0)

笔记

  • 请记住,你可以将其粘贴到上面项目代码中的 transformExample() 方法中。
  • 由于我们将在这里处理两个维度,tz 将设置为 0
  • 上图中的红线从原始位置的中心到新位置的中心。这是因为变换是相对于锚点完成的,默认情况下锚点位于图层的中心。

规模

缩放变换拉伸或取消该层。基本语法是

CATransform3DMakeScale(sx: CGFloat, sy: CGFloat, sz: CGFloat)

其中 sxsysz 分别是缩放(乘)x,y 和 z 坐标的数字。

StackOverflow 文档

如果我们想要宽度的一半和高度的三倍,我们将执行以下操作

myLayer.transform = CATransform3DMakeScale(0.5, 3.0, 1.0)

笔记

  • 由于我们只是在两个维度上工作,我们只需将 z 坐标乘以 1.0 即可使它们不受影响。
  • 上图中的红点表示锚点。注意如何相对于锚点完成缩放。也就是说,一切都朝向或远离锚点拉伸。

旋转

旋转变换围绕锚点旋转图层(默认情况下为图层的中心)。基本语法是

CATransform3DMakeRotation(angle: CGFloat, x: CGFloat, y: CGFloat, z: CGFloat)

其中 angle 是弧应该旋转的角度,xyz 是旋转的轴。将轴设置为 0 可取消围绕该特定轴的旋转。

StackOverflow 文档

如果我们想要将图层顺时针旋转 30 度,我们将执行以下操作:

let degrees = 30.0
let radians = CGFloat(degrees * M_PI / 180)
myLayer.transform = CATransform3DMakeRotation(radians, 0.0, 0.0, 1.0)

笔记

  • 由于我们在两个维度上工作,我们只希望 xy 平面绕 z 轴旋转。因此我们将 xy 设置为 0.0 并将 z 设置为 1.0
  • 这使图层顺时针旋转。我们可以通过将 z 设置为 -1.0 来逆时针旋转。
  • 红点显示锚点的位置。围绕锚点完成旋转。

多次转换

为了组合多个变换,我们可以像这样使用 concatination

CATransform3DConcat(a: CATransform3D, b: CATransform3D)

但是,我们将一个接一个地做。第一个转换将在其名称中使用 Make。以下变换不会使用 Make,但它们会将先前的变换作为参数。

StackOverflow 文档

这次我们将前三个变换结合起来。

let degrees = 30.0
let radians = CGFloat(degrees * M_PI / 180)

// translate
var transform = CATransform3DMakeTranslation(90, 50, 0)

// rotate
transform = CATransform3DRotate(transform, radians, 0.0, 0.0, 1.0)

// scale
transform = CATransform3DScale(transform, 0.5, 3.0, 1.0)

// apply the transforms
myLayer.transform = transform

笔记

  • 变换在事务中完成的顺序。
  • 一切都是关于锚点(红点)完成的。

关于锚点和位置的注记

我们在不改变锚点的情况下完成了上述所有变换。有时候有必要改变它,就像你想要围绕中心的其他点旋转一样。但是,这可能有点棘手。

锚点和位置都在同一个地方。锚点表示为图层坐标系的单位(默认为 0.5, 0.5),位置在超层坐标系中表示。它们可以像这样设置

myLayer.anchorPoint = CGPoint(x: 0.0, y: 1.0)
myLayer.position = CGPoint(x: 50, y: 50)

如果仅设置锚点而不更改位置,则框架会发生变化,以使位置位于正确的位置。或者更确切地说,基于新的锚点和旧位置重新计算框架。这通常会产生意外结果。以下两篇文章对此进行了很好的讨论。

也可以看看

此示例最初来自此 Stack Overflow 示例