ios 如何在 CALayer 上进行转换?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34438889/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 08:28:09  来源:igfitidea点击:

How to do transforms on a CALayer?

iosswifttransformcalayer

提问by Suragch

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.

但是,我仍然无法理解如何在layer上进行基本转换。寻找平移、旋转和缩放的解释和简单示例一直很困难。

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.
  • At this point I am only concerned with understanding 2D transforms.
  • 我只做 Swift,但如果其他人想添加 Objective-C 代码,请成为我的客人。
  • 在这一点上,我只关心理解 2D 变换。

回答by Suragch

Basics

基本

There are a number of different transforms you can do on a layer, but the basic ones are

您可以在图层上进行许多不同的变换,但基本的变换是

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

enter image description here

在此处输入图片说明

To do transforms on a CALayer, you set the layer's transformproperty to a CATransform3Dtype. For example, to translate a layer, you would do something like this:

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

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

The word Makeis used in the name for creating the initial transform: CATransform3DMakeTranslation. Subsequent transforms that are applied omit the Make. See, for example, this rotation followed by a translation:

这个词Make用于创建初始变换的名称:CATransform3D MakeTranslation。应用的后续变换将省略Make. 例如,请参阅此旋转后跟平移:

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 UIViewwith a light blue background to the storyboard. I hooked up the view to the view controller with the following code:

对于以下示例,我设置了一个单一视图应用程序,并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.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 CATextLayerso 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 txis the change in the x coordinates, tyis the change in y, and tzis the change in z.

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

Example

例子

enter image description here

在此处输入图片说明

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.
  • Since we are just going to deal with two dimensions here, tzis set to 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.
  • 请记住,您可以将其粘贴到transformExample()上面项目代码中的方法中。
  • 由于我们在这里只处理两个维度,tz因此设置为0
  • 上图中的红线从原始位置的中心到新位置的中心。这是因为转换是相对于锚点完成的,并且默认情况下锚点位于图层的中心。

Scale

规模

The scale transform stretches or squishes the layer. The basic syntax is

缩放变换会拉伸或挤压图层。基本语法是

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

where sx, sy, and szare the numbers by which to scale (multiply) the x, y, and z coordinates respectively.

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

Example

例子

enter image description here

在此处输入图片说明

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.
  • 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.
  • 由于我们只在二维中工作,我们只需将 z 坐标乘以 1.0 以使其不受影响。
  • 上图中的红点代表锚点。注意缩放是如何相对于锚点完成的。也就是说,一切都朝着或远离锚点拉伸。

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 angleis the angle in radians that the layer should be rotated and x, y, and zare the axes about which to rotate. Setting an axis to 0 cancels a rotation around that particular axis.

其中angle是以弧度为单位的图层应旋转的角度xy, 和z是旋转的轴。将轴设置为 0 会取消围绕该特定轴的旋转。

Example

例子

enter image description here

在此处输入图片说明

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. Thus we set xand yto 0.0and set zto 1.0.
  • This rotated the layer in a clockwise direction. We could have rotated counterclockwise by setting zto -1.0.
  • The red dot shows where the anchor point is. The rotation is done around the anchor point.
  • 由于我们在两个维度上工作,我们只希望 xy 平面围绕 z 轴旋转。因此,我们设定xy0.0和集z1.0
  • 这将按顺时针方向旋转图层。我们可以通过设置z为逆时针旋转-1.0
  • 红点表示锚点的位置。旋转是围绕锚点完成的。

Multiple transforms

多次变换

In order to combine multiple transforms we could use concatination like this

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

CATransform3DConcat(a: CATransform3D, b: CATransform3D)

However, we will just do one after another. The first transform will use the Makein its name. The following transforms will not use Make, but they will take the previous transform as a parameter.

然而,我们只会一个接一个地做。第一个转换将Make在其名称中使用 。下面的转换将不会使用Make,但它们会将之前的转换作为参数。

Example

例子

enter image description here

在此处输入图片说明

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. They can be set like this

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

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

也可以看看