javascript - How to combine element transformations? - Stack Overflow

In HTML5 I want to implement transform functionality to canvas element, so user can translate (move), s

In HTML5 I want to implement transform functionality to canvas element, so user can translate (move), scale (zoom in/out) and rotate the canvas element. Each such tranformation can be done with different transform-origin point.

First tranformation is easy:

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');

User will move or zoom or rotate the element, not everything at once, so some parameters of tranformation will stay default (dx = 0, dy = 0, zoom = 1, angle = 0).

After such tranformation, if user wants to make another transformation (and antother, and another...), how can I bine (dx1, dy1, zoom1, angle1, cx1, cy1) with (dx2, dy2, zoom2, angle2, cx2, cy2) to get final values that can be bine later with new tranformation parameters? I cannot append another tranformation to transform parameter, because tranform-origin may be different. Is there a formula how to bine tranformations with different transform-origin points?

In HTML5 I want to implement transform functionality to canvas element, so user can translate (move), scale (zoom in/out) and rotate the canvas element. Each such tranformation can be done with different transform-origin point.

First tranformation is easy:

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');

User will move or zoom or rotate the element, not everything at once, so some parameters of tranformation will stay default (dx = 0, dy = 0, zoom = 1, angle = 0).

After such tranformation, if user wants to make another transformation (and antother, and another...), how can I bine (dx1, dy1, zoom1, angle1, cx1, cy1) with (dx2, dy2, zoom2, angle2, cx2, cy2) to get final values that can be bine later with new tranformation parameters? I cannot append another tranformation to transform parameter, because tranform-origin may be different. Is there a formula how to bine tranformations with different transform-origin points?

Share Improve this question edited Jul 29, 2012 at 8:55 Rich Bradshaw 73.1k46 gold badges188 silver badges241 bronze badges asked Jul 14, 2012 at 21:48 ΩmegaΩmega 43.7k35 gold badges142 silver badges212 bronze badges 3
  • Have you tried to visualize it? Draw a box on a paper. Then, consider what happens when you want to translate/rotate/scale the box. And again. – Rob W Commented Jul 14, 2012 at 21:52
  • @RobW - I tried a lot for over a week :-/ I am able to bine unlimited move (translate) and zoom (scale) tranformations, but once I have rotation involved, I am lost... – Ωmega Commented Jul 14, 2012 at 22:00
  • I'm not sure the linear-algebra tag belongs on this question. It's more about bining CSS properties than using linear algebra. – TylerH Commented Jun 7, 2015 at 18:15
Add a ment  | 

2 Answers 2

Reset to default 9

You don't have to learn matrix math. According to the CSS Transform specification

  1. Start with the identity matrix.
  2. Translate by the puted X, Y and Z values of ‘transform-origin’.
  3. Multiply by each of the transform functions in ‘transform’ property in turn
  4. Translate by the negated puted X, Y and Z values of ‘transform-origin’

In other words, transform-origin: A; transform: B is the same as transform: translate(-A) B translate(A). (Transformations apply from right to left, so the first thing you want to happen goes at the end.)

So use the above rules to eliminate transform-origin and now you just have plain transforms you can concatenate.

Example:

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

bees

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

Now you can bine them since they all agree on the origin (i.e., 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 the consecutive translations if you want

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

Or you can dig out your math textbook and pute the final transformation matrix.

Edit: Transforms apply right to left.

You'd have to deal with matrix transformations.

Every linear operation can be represented with a 3x3 matrix and a 3x1 vector that you can apply on the point of the plane. If p is a point, M the matrix and q the other vectory, every linear transformation can be represented as Mp + q.

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

For translations, the matrix is just the identity matrix. The vector q is the translation vector.

For scaling, M is like

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

where a and b are scaling factor for x and y respectively. The vector q is null.

For rotations, say of an angle a, you'll get

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

and q is null again.

There are matrices for skewing, too. So, if you have to apply three consecutive transformations, you'll have to apply these kind of linear transformations. Your problem is that you have to deal with origins, too, so you'll have to subtract the vector o from p, than apply M, add q and then o again.

Let's say you have these transformation (M1, q1, o1) and (M2, q2, o2). When you apply the first one you get

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

Then you have to apply the second transformation:

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

In the end you'll get:

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

And so on with and eventual third (M3, q3, o3).

A mess? It looks like. But things can be simplyfied a bit if you know how the matrices look like.

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

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744185741a4562197.html

相关推荐

  • javascript - How to combine element transformations? - Stack Overflow

    In HTML5 I want to implement transform functionality to canvas element, so user can translate (move), s

    8天前
    10

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信