Matrix: CGAffineTransform, CATransform3D

CGAffineTransform

The affine transform 2D, CG prefix tells us that the CGAffineTransform type belongs to the Core Graphics framework. Core Graphics is actually a STRICT 2D drawing API, and CGAffineTransform is only valid for 2D transformations.

It uses a 3*3 matrix and can be used for rotation, scaling and translation of layers under 2D conditions.

A single conversion

// let tr = CGAffineTransform(rotationAngle: Let tr = CGAffineTransform(scaleX: 0.1, y: Let tr = CGAffineTransform(translationX: 0, y: translationX: 0, y: translationX: 0) 100) / / CGAffineTransform join newView. In the view layer. SetAffineTransform (tr)Copy the code

Combination of transformation

// In the combination transformation, the result of the previous transformation will affect the position and size of the subsequent transformation. Instead of a one-time transform from the start position let TRS = CGAffineTransform(rotationAngle: CGFloat(M_PI_4)).scaledby (x: 2, y: 1).translatedBy(x: 100, y: 0) .inverted() newView.layer.setAffineTransform(trs)Copy the code

CATransform3D

3D transform, used to adjust the distance between the layer and the user’s perspective.

In learning, we know that this is a 4*4 matrix, CATransform3D has a total of 16 variables from M11 to M44, the structure is as follows:

public struct CATransform3D {

    public var m11: CGFloat
		....
    public var m44: CGFloat

    public init()

    public init(m11: CGFloat, m12: CGFloat, m13: CGFloat, m14: CGFloat, m21: CGFloat, m22: CGFloat, m23: CGFloat, m24: CGFloat, m31: CGFloat, m32: CGFloat, m33: CGFloat, m34: CGFloat, m41: CGFloat, m42: CGFloat, m43: CGFloat, m44: CGFloat)
}
Copy the code

The matrix diagram is as follows:

And each variable represents the value, is a 3D transformation of an action, such as our most commonly used translation, scaling and rotation, is by the combination of these 4*4, in the source notes will be able to explore

# This is a default structure for The identity transform: [1 0 0 0; 0 1 0 0; 0 0 1 0; 0 0 0 1 0; 0 0 0 1]. Returns a transform that translates by '(tx, ty, tz)': * t' = [1 0 0 0; 0 1 0 0; 0 0 1 0; tx ty tz 1]. Returns a transform that scales by '(sx, SY, Sz)': * t' = [sx 0 0 0; 0 sy 0 0; 0 0 sz 0; 0 0 0 0 1]. Rotate 't' by 'Angle' radians about the vector '(x, y, z)' and return * the result. If the vector has zero length the behavior is undefined: Rotation (Angle, x,y,z) * t' = rotation(Angle, x,y,z) * t. #m34 That is, consistent with the axial system that it represents; When we use the rotation operation, it's backwards, in the matrix m12 and M21 are not on the z axis, m23 and M32 are not on the y axis, and here it's calculated in an interesting way. Because there is no deep digging, can only push this step, hope to know friends can tell one or twoCopy the code

There are rotations everywhere

Add z transform (Perspective)

We choose to use CATransform3D, mainly because we need the effect of 3D rotation, otherwise we can completely consider a simpler 2D scheme to achieve

M34 represents the perspective effect, and the value is -1/d. The smaller d is, the more obvious the perspective is and the more obvious the rotation effect is. It must be set when there is rotation.

Var tr3D = CATransform3DIdentity Tr3d. m34 = -1/100 tr3D = CATransform3DRotate(tr3D, CGFloat(M_PI_4), 0, 0, 1) / / no need perspective effect, do not need to add the 't' tr3D = CATransform3DMakeRotation (CGFloat (M_PI_4), 0, 1, 0) newView. Layer. The transform = tr3DCopy the code

Generally, the back of the layer is drawn at the same time, and the displayed content is a mirror of the front. When we do not need the back content, we can use isDoubleSided to avoid waste of resources. The layer will not be drawn or ided to display anything, and the layer will remain in the view

newView.layer.isDoubleSided = false
Copy the code

conversion

There are methods for converting both in CATransform3D

func CATransform3DMakeAffineTransform(_ m: CGAffineTransform) -> CATransform3D
func CATransform3DGetAffineTransform(_ t: CATransform3D) -> CGAffineTransform
Copy the code

Flattening mechanism

Flattening is mainly in 3D layered scenes (extended content CATransformLayer)

Since Core Animation layers exist in 3D space, they do not all exist in the same 3D space. The 3D scene of each layer is actually flattened, so when we look at a layer from the front, we actually see an imaginary 3D scene created by the sub-layers, but if we tilt the layer, we see that the 3D scene is actually just drawn on the surface of the layer.

Therefore, in use, if we rotate along the axis of the screen, we will see two-dimensional content, and if we rotate along the vertical axis of the screen, we will see three-dimensional content, and this three-dimensional content is a kind of dimensional perception drawn according to the Angle.

It can be concluded that:

(1) When we reverse the direction of the inner layer of the converted layer, the effect of the inner layer will be cancelled.

(2) Each parent view flattens its children.

Vanishing point

The vanishing point is the center of the 3D content-centered view, which changes when we change the position of the layer

If you want to ensure that all layers share the same quench point, you need to set each layer separately and ensure that it has the same M34 value, and that the quench point is the same until the layer changes. You can also use the sublayerTransform property to manage the perspective and extinction points of the children through a parent layer’s sublayerTransform.

conclusion

Matrices can manage the state of layer rotation, placement or distortion, and CATransform3D can transform flat objects into three-dimensional space objects. It’s very helpful for us to study layer techniques in 3d space, not just adding rounded corners, shadows and other basic operations.