How to combine element transformations?

In HTML5, I want to implement a transform function for a canvas element, so the user can translate (move), scale (increase / decrease) and rotate the canvas element. Each such transformation can be performed with a different point of origin of the transformation.

The first transformation is simple:

 function transform(el, value, origin) { el.style.Transform = value; el.style.MozTransform = value; el.style.msTransform = value; el.style.OTransform = value; el.style.webkitTransform = value; el.style.TransformOrigin = origin; el.style.MozTransformOrigin = origin; el.style.msTransformOrigin = origin; el.style.OTransformOrigin = origin; el.style.webkitTransformOrigin = origin; } transform(myCanvas, 'translate('+ dx +'px, ' + dy + 'px) ' + 'scale(' + zoom + ', ' + zoom + ') ' + 'rotate(' + angle + 'deg)', cx + 'px ' + cy + 'px'); 

The user will move or scale or rotate the element, but not all at once, so some tranformation parameters will remain by default (dx = 0, dy = 0, zoom = 1, angle = 0).

After such a transformation, if the user wants to do another transformation (both antother and more ...), how can I combine (dx1, dy1, zoom1, angle1, cx1, cy1) with (dx2, dy2, zoom2, angle2, cx2, cy2) to get final values ​​that can be combined later with new tranformation parameters? I cannot add another transformation to the transform parameter, because tranform-origin may be different. Is there a formula for combining triangulation with different points of origin of transformation?

+4
source share
2 answers

You do not need to study a mathematical matrix. According to CSS Transform specification

  • Start with the identity matrix.
  • Translate to calculated values ​​X, Y and Z 'transform-origin.
  • Multiply each of the conversion functions into a 'conversion property in turn
  • Translate to negative calculated values ​​X, Y and Z 'transform-origin

In other words, transform-origin: A; transform: B transform-origin: A; transform: B same as transform: translate(-A) B translate(A) . (Transforms are applied from right to left, so the first thing you want happens at the end.)

So use the rules above to eliminate transform-origin , and now you have simple transformations that you can combine.

Example:

  • transform-origin: 5px 5px; transform: translate(10px, 40px)
  • transform-origin: 25px 30px; transform: scale(2)
  • transform-origin: 10px 10px; transform: rotate(30deg)

becomes

  • transform: translate(-5px, -5px) translate(10px, 40px) translate(5px, 5px)
  • transform: translate(-25px, -30px) scale(2) translate(25px, 30px)
  • transform: translate(-10px, -10px) rotate(30deg) translate(10px, 10px)

Now you can combine them, as they all agree with the beginning (i.e. there is no origin)

transform: translate(-5px, -5px) translate(10px, 40px) translate(5px, 5px) translate(-25px, -30px) scale(2) translate(25px, 30px) translate(-10px, -10px) rotate(30deg) translate(10px, 10px)

Of course you can collapse consecutive translations if you want

transform: translate(-15px, 10px) scale(2) translate(15px, 20px) rotate(30deg) translate(10px, 10px)

Or you can dig up your math textbook and calculate the final transformation matrix .

Change Conversions are applied from right to left.

+8
source

You will have to deal with matrix transformations.

Each linear operation can be represented by a 3x3 matrix and a 3x1 vector, which you can apply at a point in the plane. If p is a point, M is a matrix, and q is another, then each linear transformation can be represented as Mp + q.

If you have a 2d point, then its vector will be [x; y; 1] (vertical vector), and the matrix can take several forms.

For translations, the matrix is ​​only an identity matrix. Vector q is a shift vector.

For scaling, M is similar to

  [a 0 0] M = [0 b 0] [0 0 1] 

where a and b are the scaling factors for x and y, respectively. Vector q is zero.

To rotate, say, at an angle a, you get

  [cos(a) -sin(a) 0] M = [sin(a) cos(a) 0] [ 0 0 1] 

and q is null again.

There are also skew matrices. So, if you need to apply three consecutive transformations, you will have to apply such linear transformations. Your problem is that you have to deal with the origin, so you have to subtract the vector o from p, than apply M, add q, and then o again.

Say you have this conversion (M1, q1, o1) and (M2, q2, o2). When you apply the first, you get

 p1 = M1 * (p - o1) + q1 + o1 

Then you need to apply the second transformation:

 p2 = M2 * (p1 - o2) + q2 + o2 

As a result, you will receive:

 p2 = M2 * (M1 * (p - o1) + q1 + o1 - o2) + q2 + o2 

And so on and finally the third (M3, q3, o3).

A mess? It looks like. But everything can be simplified a little if you know how matrices look.

Now do the math and apply it to transform: matrix(a, b, c, d, tx, ty) .

+1
source

All Articles