div.example {
transform: rotate(45deg) skewX(33deg);
transform-origin(150% 33%);
width:100px;
height: 100px;
}
The element's bounding box will be a transparent blue and has the dimensions of width:97px, height:187px
The transformed element will have a containing bounding box's left and top properties set in order to
illustrate each step.
A rotation of 45 degrees, and skewing about the x axis 33 degrees will result in the following matrix
(I've truncated to 4 decimal places):
| 0.7071 | -0.2479 |
| 0.7071 | 1.1663 |
width:100px; height: 100px;Take the original center of the element and translate it by the negated transform origin.
center = (50, 50) origin = (100 * 150%, 100 * 33%) = (150, 33) translated center = (50 - 150, 50 - 33) = (-100, 17)Apply the matrix transform to the result.
[[0.7071, -0.2479], [0.7071, 1.1663]] * [-100, 17] = [0.7071 * -100 + -0.2479 * 17, 0.7071 * -100 + 1.1663 * 17] = [-74.9242, -50.8834]Translate the result by the transform origin.
[-74.9242 + 150, -50.8834 + 33] = [75.0758, -17.8834]Subtract from the x value of the result half the width of the bounding box, and from the y value of the result half the height of the bounding box.
[75.0758 - 97/2, -17.8834 - 187/2] ~= [26.5, -112]This is where the top left corner of the bounding box should be Actual Code:
#true-transform {
-moz-transform: rotate(45deg) skewX(33deg);
-moz-transform-origin: 150% 33%;
-webkit-transform: rotate(45deg) skewX(33deg);
-webkit-transform-origin: 150% 33%;
Mathematically, this is nothing new, it's really just the algorithm for
transforming a point or set of points (think corners of a polygon) about an origin which is:
(一)Translate by the negated value of the origin.
(二)Apply the transform to the points, i.e the matrix.
(三)Translate by the origin.
The tough part is the origin dimensions, I don't have a viewport change listener or anything
going on, so if the screen is resized in anyway then the effects won't be consistent in ie since
the code has sized the element but all in all I think it's working pretty well.
elTransform('id-of-element').
origin('left top').
matrix({rotate:60/*degrees*/});
All methods that require an angle are normalized to degrees. You're welcome to
modify the code as you see fit, personally I find working with bulky floating point
numbers due to radians a pain in the wrist.
Another thing is all code (minus the MatrixAnim class) is library agnostic. You're free to drop it in and
muddle with it as you see fit. Using a solid library to handle some of the plumbing will
probably stablize the code even more.
var anim = new MatrixAnim('some-element', {
rotate: {
by: 360
},
scale :{by:0.25},
skewY : {from:10, to:45}
}, 3, YAHOO.util.Easing.bounceOut);
//kick off the animation
anim.animate ();
| a | b |
| c | d |
| 0.7071 | -0.7071 |
| 0.7071 | 0.7071 |
-moz-transform: rotate(45deg); -webkit-transform: rotate(45deg);I am an example 45 degree rotation -(moz|webkit)-transform: matrix(0.7071, -0.7071, 0.7071, 0.7071, 0, 0); I am an example With an equivalent 45 degree matrix, But I'm going the wrong way.
| a | b |
| c | d |
-moz-transform: rotate(45deg); -webkit-transform: rotate(45deg);I am an example Been rotated 45 degrees -(moz|webkit)-transform: matrix(0.7071, 0.7071, -0.7071, 0.7071, 0, 0); Now I'm rotated the right way. Some other nuances between firefox and safari. If you apply the transform to an element and query the element's position, for instance this element above Firefox will consistenly return 101 x 101. Webkit's results are very inconsistent, I wasn't able to track down a pattern or any rhyme or reason to it. In my origin manipulation example I had to get the region of the animated element outside of my drag drop end handler. I found if I got the region of the element in the handler while the element was being animated the element would shoot all over the place. Last Modified 9/18/2009 4:33 PM PST