问题
I've got a cube element being rotated and translated in a 3d space.
I want to find out just the rotateY portion of this transform at a given time. Is this possible?
I have:
var cube = document.getElementById("cube");
var transform = getComputedStyle(cube).webkitTransform;
//the value of transform is:
// matrix3d(-1, 0, 0.00000000000000012246467991473532, 0,
// 0, 1, 0, 0,
// -0.00000000000000012246467991473532, 0, -1, 0,
// 0, 0, 0, 1)
Help? :-)
回答1:
If your object is only being rotated about Y, then yes, the rotation is simple to calculate - it's the arccos of Matrix elements 1,1 or 3,3 or the arsin of -(element 3,1) or arcsin of element 1,3. In your specific example, it's about 180 degrees. If the rotations are about more than just the y axis, then you have to start tracking previous rotations and it can get messier.
Your translation will just be the bottom row of the output matrix, 0,0,0 in this case.
See examples on http://www.inversereality.org/tutorials/graphics%20programming/3dwmatrices.html
回答2:
You can retrieve transformation informations with the "new WebKitCSSMatrix" function. For example :
var matrix = new WebKitCSSMatrix($('#element').css('-webkit-transform'));
var translateZ = matrix.m43;
Each part of the matrix is explain here : http://9elements.com/html5demos/matrix3d/ You can retrieve more complexe properties like rotationX, for 3d matrix with math mess :
var rotationX = Math.acos(matrix.a) * (180/Math.PI);
var rotationY = Math.asin(matrix.b) * (180/Math.PI);
回答3:
Given function determines rotation*
, transform*
and scale
for given DOM element cross-browser.
If you want something more, or find bugs in mathematics, it's a discussion on math.stackexchange.com
Tested on browsers listed in http://caniuse.com/transforms3d:
var reverseEngineerTransform3d = function (domElement, parameterName) {
parameterName = parameterName.toLowerCase();
var computedStyle = window.getComputedStyle(domElement),
matrixStyle = computedStyle.transform || computedStyle.WebkitTransform || computedStyle.MozTransform || computedStyle.msTransform || computedStyle.OTransform;
if (matrixStyle) {
matrixStyle = matrixStyle.trim();
}
if (matrixStyle === 'none') {
if (parameterName.indexOf('rotate') === 0) {
return '0deg';
} else if (parameterName.indexOf('translate') === 0) {
return '0px';
} else if (parameterName === 'scale') {
return 1;
} else {
throw "Unsupported 3D parameter " + parameterName;
}
}
else if (!matrixStyle || matrixStyle.substr(0, 9) !== 'matrix3d(') {
//return something or die ?????
throw "Something is wrong with 3D transform style. Probably no style applied at all OR unknown CSS3 vendor OR unknown/unsupported 3D matrix representation string OR CSS3 3D transform is not fully supported in this browser";
}
var matrix = window.WebKitCSSMatrix && (new WebKitCSSMatrix(matrixStyle)) ||
window.MozCSSMatrix && (new MozCSSMatrix(matrixStyle)) ||
window.MsCSSMatrix && (new MsCSSMatrix(matrixStyle)) ||
window.OCSSMatrix && (new OCSSMatrix(matrixStyle)) ||
window.CSSMatrix && (new CSSMatrix(matrixStyle)); // sorry 4 copy-paste my friends
if (!matrix || isNaN(matrix.a) || isNaN(matrix.b) || isNaN(matrix.c) || isNaN(matrix.m41) || isNaN(matrix.m42) || isNaN(matrix.m43) || isNaN(matrix.m11)) {
throw "Could not catch CSSMatrix constructor for current browser, OR the constructor has returned a non-standard matrix object (need .a, .b, .c and mXX numerical properties to work)";
}
// todo: giving a parameters array (and returning an array) is a good idea, or we could return everything if no parameters given
switch (parameterName) {
case 'rotatey': // in degrees
return Math.acos(matrix.m11)*180/Math.PI * (matrix.m13 > 0 ? -1 : 1) + 'deg';
case 'rotatex': // in degrees
return Math.asin(matrix.m22)*180/Math.PI + 'deg';
case 'rotatez': // in degrees
throw "TODO: Sorry, math people. I really need help here! Please implement this case for me. This will help you: http://9elements.com/html5demos/matrix3d/";
case 'translatex': // in pixels
return matrix.m41 + 'px';
case 'translatey': // in pixels
return matrix.m42 + 'px';
case 'translatez': // in pixels
return matrix.m43 + 'px';
case 'scale': // no units
if (matrix.m11 === matrix.m22 && matrix.m22 === matrix.m33) {
return matrix.m11;
} else {
throw "I'm not so smart to calculate scale from this matrix";
}
// todo: anything else? skew ????
default:
throw "This function accepts 3d-parameter name (case-insensitive string) as the second argument. Currently supported: 'rotate[xyz]', 'translate[xyz]', 'scale'. This parameter is unsupported: " + parameterName;
}
};
来源:https://stackoverflow.com/questions/10592823/how-to-reverse-engineer-a-webkit-matrix3d-transform