简体   繁体   English

如何在CALayer上进行转换?

[英]How to do transforms on a CALayer?

Before writing this question, I've 在写这个问题之前,我已经

However, I'm still having trouble understanding how to do basic transforms on a layer . 但是,我仍然无法理解如何在图层上进行基本变换。 Finding explanations and simple examples for translate, rotate and scale has been difficult. 寻找翻译,旋转和缩放的解释和简单示例一直很困难。

Today I finally decided to sit down, make a test project, and figure them out. 今天我终于决定坐下来,做一个测试项目,然后把它们搞清楚。 My answer is below. 我的答案如下。

Notes: 笔记:

  • I only do Swift, but if someone else wants to add the Objective-C code, be my guest. 我只做Swift,但如果有人想要添加Objective-C代码,请成为我的客人。
  • At this point I am only concerned with understanding 2D transforms. 在这一点上,我只关心理解2D变换。

Basics 基本

There are a number of different transforms you can do on a layer, but the basic ones are 您可以在一个图层上执行许多不同的变换,但基本的变换是

  • translate (move) 翻译(移动)
  • scale 规模
  • rotate 回转

在此输入图像描述

To do transforms on a CALayer , you set the layer's transform property to a CATransform3D type. 要在CALayer上执行变换,请将图层的transform属性设置为CATransform3D类型。 For example, to translate a layer, you would do something like this: 例如,要翻译图层,您可以执行以下操作:

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

The word Make is used in the name for creating the initial transform: CATransform3D Make Translation. 在创建初始变换的名称中使用单词Make :CATransform3D Make Translation。 Subsequent transforms that are applied omit the Make . 应用的后续转换省略了Make See, for example, this rotation followed by a translation: 例如,请参阅此轮换后跟翻译:

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

Now that we have the basis of how to make a transform, let's look at some examples of how to do each one. 既然我们已经有了如何进行变换的基础,那么让我们看看如何做每个变换的一些例子。 First, though, I'll show how I set up the project in case you want to play around with it, too. 首先,我将展示如何设置项目,以防您想要玩它。

Setup 建立

For the following examples I set up a Single View Application and added a UIView with a light blue background to the storyboard. 对于以下示例,我设置了单视图应用程序,并在故事板中添加了浅蓝色背景的UIView I hooked up the view to the view controller with the following code: 我使用以下代码将视图连接到视图控制器:

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.blue.cgColor
        myLayer.string = "Hello"
        myView.layer.addSublayer(myLayer)
    }

    //******** Replace this function with the examples below ********

    func transformExample() {

        // add transform code here ...


    }

} 

There are many different kinds of CALayer , but I chose to use CATextLayer so that the transforms will be more clear visually. 有许多不同种类的CALayer ,但我选择使用CATextLayer以便视觉上的变换更加清晰。

Translate 翻译

The translation transform moves the layer. 平移变换移动图层。 The basic syntax is 基本语法是

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

where tx is the change in the x coordinates, ty is the change in y, and tz is the change in z. 其中tx是x坐标的变化, ty是y的变化, tz是z的变化。

Example

在此输入图像描述

In iOS the origin of the coordinate system is in the top left, so if we wanted to move the layer 90 points to the right and 50 points down, we would do the following: 在iOS中,坐标系的原点位于左上角,因此如果我们想将图层向右移动90点,向下移动50点,我们将执行以下操作:

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

Notes 笔记

  • Remember that you can paste this into the transformExample() method in the project code above. 请记住,您可以将其粘贴到上面项目代码中的transformExample()方法中。
  • Since we are just going to deal with two dimensions here, tz is set to 0 . 由于我们将在这里处理两个维度,因此tz设置为0
  • The red line in the image above goes from the center of the original location to the center of the new location. 上图中的红线从原始位置的中心到新位置的中心。 That's because transforms are done in relation to the anchor point and the anchor point by default is in the center of the layer. 这是因为变换是相对于锚点完成的,默认情况下锚点位于图层的中心。

Scale 规模

The scale transform stretches or squishes the layer. 缩放变换拉伸或取消该层。 The basic syntax is 基本语法是

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

where sx , sy , and sz are the numbers by which to scale (multiply) the x, y, and z coordinates respectively. 其中sxsysz分别是缩放(乘)x,y和z坐标的数字。

Example

在此输入图像描述

If we wanted to half the width and triple the height, we would do the following 如果我们想要宽度的一半和高度的三倍,我们将执行以下操作

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

Notes 笔记

  • Since we are only working in two dimensions, we just multiply the z coordinates by 1.0 to leave them unaffected. 由于我们只是在两个维度上工作,我们只需将z坐标乘以1.0即可使它们不受影响。
  • The red dot in the image above represents the anchor point. 上图中的红点代表锚点。 Notice how the scaling is done in relation to the anchor point. 注意如何相对于锚点完成缩放。 That is, everything is either stretched toward or away from the anchor point. 也就是说,一切都朝向或远离锚点拉伸。

Rotate 旋转

The rotation transform rotates the layer around the anchor point (the center of the layer by default). 旋转变换围绕锚点旋转图层(默认情况下为图层的中心)。 The basic syntax is 基本语法是

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

where angle is the angle in radians that the layer should be rotated and x , y , and z are the axes about which to rotate. 其中, angle是弧度应该旋转的角度, xyz是要旋转的轴。 Setting an axis to 0 cancels a rotation around that particular axis. 将轴设置为0可取消围绕该特定轴的旋转。

Example

在此输入图像描述

If we wanted to rotate a layer clockwise 30 degrees, we would do the following: 如果我们想要将图层顺时针旋转30度,我们将执行以下操作:

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

Notes 笔记

  • Since we are working in two dimentions, we only want the xy plane to be rotated around the z axis. 由于我们在两个维度上工作,我们只希望xy平面围绕z轴旋转。 Thus we set x and y to 0.0 and set z to 1.0 . 因此我们将xy设置为0.0并将z设置为1.0
  • This rotated the layer in a clockwise direction. 这使层顺时针旋转。 We could have rotated counterclockwise by setting z to -1.0 . 我们可以通过将z设置为-1.0来逆时针旋转。
  • The red dot shows where the anchor point is. 红点表示锚点的位置。 The rotation is done around the anchor point. 围绕锚点完成旋转。

Multiple transforms 多次转换

In order to combine multiple transforms we could use concatination like this 为了组合多个变换,我们可以像这样使用concatination

CATransform3DConcat(a: CATransform3D, b: CATransform3D)

However, we will just do one after another. 但是,我们将一个接一个地做。 The first transform will use the Make in its name. 第一个转换将使用其名称中的Make The following transforms will not use Make , but they will take the previous transform as a parameter. 以下转换不会使用Make ,但它们会将先前的转换作为参数。

Example

在此输入图像描述

This time we combine all three of the previous transforms. 这次我们将前三个变换结合起来。

let degrees = 30.0
let radians = CGFloat(degrees * Double.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

Notes 笔记

  • The order that the transforms are done in matters. 变换在事务中完成的顺序。
  • Everything was done in relation to the anchor point (red dot). 一切都是关于锚点(红点)完成的。

A Note about Anchor Point and Position 关于锚点和位置的注记

We did all our transforms above without changing the anchor point. 我们在不改变锚点的情况下完成了上述所有变换。 Sometimes it is necessary to change it, though, like if you want to rotate around some other point besides the center. 有时候有必要改变它,就像你想要围绕中心以外的其他点旋转一样。 However, this can be a little tricky. 但是,这可能有点棘手。

The anchor point and position are both at the same place. 锚点和位置都在同一个地方。 The anchor point is expressed as a unit of the layer's coordinate system (default is 0.5, 0.5 ) and the position is expressed in the superlayer's coordinate system. 锚点表示为层的坐标系统的单元(默认为0.5, 0.5 )和位置在superlayer的坐标系统中表示。 They can be set like this 它们可以像这样设置

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

If you only set the anchor point without changing the position, then the frame changes so that the position will be in the right spot. 如果仅设置锚点而不更改位置,则框架会发生变化,以使位置位于正确的位置。 Or more precisely, the frame is recalculated based on the new anchor point and old position. 或者更确切地说,基于新的锚点和旧位置重新计算框架。 This usually gives unexpected results. 这通常会产生意外结果。 The following two articles have an excellent discussion of this. 以下两篇文章对此进行了很好的讨论。

See also 也可以看看

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM