📜 ⬆️ ⬇️

Lost documentation or transform: matrix3d ​​[translation]

When you dive into the CSS3 transform: matrix3d ​​documentation, you find a short definition of "Specifies a 3D transformation as a 4x4 matrix.", Followed by a function definition in the form:

matrix3d(m00, m01, m02, m03,
m10, m11, m12, m13,
m20, m21, m22, m23,
m30, m31, m31, m33)


And if you are not the god of mathematics, most likely, inside there is a concern about the lack of documentation, followed by the question of how to create a really cool thing? The described approach does not pretend to be called mathematical or complete - I'm just trying to fill a small gap in the documentation.

demo | original source

Some linear algebra


Any complex transformation can be represented by three basic ones:
')
Rotate
Scale
Move (translate)

These 3 basic transformations can be combined into one huge comprehensive transformation matrix. So far everything is simple, but how to move from 3 basic stages to that unchecked list of parameters that is needed for matrix3d? Let's start with the simplest matrix in mathematics (to simplify my life, I use Sylvester for mathematical operations with matrices).

Unit matrix

image

This matrix does nothing! Nil! Null! Nada! Not a single pixel was hurt! I divided this matrix into 2 sections. The red section is the area where Rotate and Scale are described. The yellow section describes a shift or translate. The remaining parameters are used very rarely, with the exception of the really weird LSD-style FX demos.

We will begin by creating a scaling matrix by multiplying the identity matrix by the scaling factor.
scaleMatrix = indentityMatrix.multiply (s)

Scaling matrix

scaleMatrix = $ M ([
[s, 0,0,0],
[0, s, 0.0],
[0,0, s, 0],
[0,0,0, s]
])

Since we do not want to transform the translate coordinates, let's replace the last scaling parameter by 1:

scaleMatrix = $ M ([
[s, 0,0,0],
[0, s, 0.0],
[0,0, s, 0],
[0,0,0,1]
])

Rotation Matrices


Rotation can be carried out around its own axis X, Y, Z at a given angle. Let's take the angle values ​​for each axis as a, b, c. Corresponding matrices representing such a transformation:

rotationXMatrix = $ M ([
[1,0,0,0],
[0, Math.cos (a), Math.sin (-a), 0],
[0, Math.sin (a), Math.cos (a), 0],
[0,0,0,1]
])

rotationYMatrix = $ M ([
[Math.cos (b), 0, Math.sin (b), 0],
[0,1,0,0],
[Math.sin (-b), 0, Math.cos (b), 0],
[0,0,0,1]
])

rotationZMatrix = $ M ([
[Math.cos (c), Math.sin (-c), 0, 0],
[Math.sin (c), Math.cos (c), 0, 0],
[0,0,1,0],
[0,0,0,1]
])

Each matrix describes a rotation around one axis.

Translate matrix

translationMatrix = $ M ([
[1,0,0,0],
[0,1,0,0],
[0,0,1,0],
[tx, ty, tz, 1]
])

The displacement matrix does not affect most pixels, but adds tx, ty, and tz values ​​to the resulting direction vector.

Fun


Yes, mathematics can be fun, and each of these matrices can be used in composition. So, if you want to rotate something around each axis and then move it a few pixels, simply multiply these matrices. That's all:

tM = rotationXMatrix
.x (rotationYMatrix)
.x (rotationZMatrix)
.x (scaleMatrix)
.x (translationMatrix)

And at the end apply the transformation to the image:
s = "matrix3d ​​("
s + = tM.e (1,1) .toFixed (10) + "," + tM.e (1,2) .toFixed (10) + "," + tM.e (1,3) .toFixed ( 10) + "," + tM.e (1,4) .toFixed (10) + ","
s + = tM.e (2,1) .toFixed (10) + "," + tM.e (2,2) .toFixed (10) + "," + tM.e (2,3) .toFixed ( 10) + "," + tM.e (2,4) .toFixed (10) + ","
s + = tM.e (3,1) .toFixed (10) + "," + tM.e (3,2) .toFixed (10) + "," + tM.e (3,3) .toFixed ( 10) + "," + tM.e (3,4) .toFixed (10) + ","
s + = tM.e (4,1) .toFixed (10) + "," + tM.e (4,2) .toFixed (10) + "," + tM.e (4,3) .toFixed ( 10) + "," + tM.e (4,4) .toFixed (10)
s + = ")"

document.getElementById ('darth-vader'). style ['- webkit-transform'] = s

Cautions


The first is that if you google a linear transformation and find examples of such matrices, you might be surprised that the matrices are slightly different. The fact is that the CSS matrix is ​​transposed — just like that, transpose the matrix and it should work.

The second is that CSS does not support the scientific form of a number (for example, 123e-15) as parameters — so you need to use toFixed (numberOfDigits) to normalize them.

Development environment

The approach works in -webkit-browsers such as Chrome or Safari, Firefox 10+ and IE 10. You can see the prefixes here caniuse.com/transforms3d . The demo only works in -webkit- and is written in coffeescript which is a bit cooler than javascript - but the compiled code should be readable. You can pick up the entire lesson and source code on github .

Demo
Original article
Facebook author
Twitter author
Sylvester's amazing Javascript library
Linear transformation article on Wikipedia

Source: https://habr.com/ru/post/166751/


All Articles