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 combine (dx1, dy1, zoom1, angle1, cx1, cy1) with (dx2, dy2, zoom2, angle2, cx2, cy2) to get final values that can be combine 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 combine tranformations with different transform-origin points?
You don’t have to learn matrix math. According to the CSS Transform specification
In other words,
transform-origin: A; transform: Bis the same astransform: 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-originand now you just have plain transforms you can concatenate.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 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 compute the final transformation matrix.
Edit: Transforms apply right to left.