Javascript:360度旋转和矩阵组成的问题 [英] Javascript: issue with 360deg rotations and matrix composition
问题描述
我之前曾问过有关透视功能的正确用法(计算和组成矩阵),现在我遇到了一个较旧的问题,而且我并不希望这仍然是一个大问题.
I asked previously about the proper function for perspective (to compute and compose a matrix), now I'm facing an older problem and I wasn't expecting this to be so much of an issue still.
基本上360度/720度只是零,我不知道如何破解以下功能来解决该问题.
Basically 360deg / 720deg is just zero and I don't know how to hack the following function to fix that.
CSSMatrix.Rotate = function(rx, ry, rz){
rx *= Math.PI / 180;
ry *= Math.PI / 180;
rz *= Math.PI / 180;
// minus sin() because of right-handed system
var cosx = Math.cos(rx), sinx = - Math.sin(rx);
var cosy = Math.cos(ry), siny = - Math.sin(ry);
var cosz = Math.cos(rz), sinz = - Math.sin(rz);
var m = new CSSMatrix();
m.m11 = m.a = cosy * cosz;
m.m12 = m.b = -cosy * sinz;
m.m13 = siny;
m.m21 = m.c = sinx * siny * cosz + cosx * sinz;
m.m22 = m.d = cosx * cosz - sinx * siny * sinz;
m.m23 = - sinx * cosy;
m.m31 = sinx * sinz - cosx * siny * cosz;
m.m32 = sinx * cosz + cosx * siny * sinz;
m.m33 = cosx * cosy;
return m;
};
当使用360度旋转(在任意轴上)组成矩阵时,CSSMatrix.rotate()
方法将创建一个旋转矩阵,对于每个角度值,我们得到angle * Math.PI / 180
,然后得到其他正弦/余弦运算,但是矩阵结果不同从常规rotateX(360deg)
的计算转换中得出.
When using 360deg rotations (on any axis) to compose a matrix, the CSSMatrix.rotate()
method is creating a rotation matrix and for each angle value we get angle * Math.PI / 180
then other sinus / cosinus operations, but the matrix result is different from a computed transform of a regular rotateX(360deg)
.
在此处查看我的小提琴,其中相同的代码不能正常工作并具有360度角度和工作正常,其角度不同于360度.
See my fiddles here where same code doesn't work properly with 360deg angle and working properly with angles different from 360deg.
我该如何解决?
推荐答案
此处的问题是CSSMatrix
polyfill代码所支持的精度.它最多支持6个小数,并将任何较小的值(正数或负数)截断为0,即小于0.000001的任何值都将转换为0.
The issue here is the precision supported by the CSSMatrix
polyfill's code. It supports upto 6 decimals and truncates any lesser value (positive or negative) to 0 i.e. anything less than 0.000001 will be converted to 0.
在您的小提琴中,如果仅应用rotateX(360deg)
转换,它将转换为此matrix3d:
In your fiddle, if you just apply the rotateX(360deg)
transform, it converts to this matrix3d:
matrix3d(1,0,0,0,0,1,-2.44929e-16,0,0,2.44929e-16,1,0,0,0,0,1)
matrix3d(1, 0, 0, 0, 0, 1, -2.44929e-16, 0, 0, 2.44929e-16, 1, 0, 0, 0, 0, 1)
polyfill将-2.44929e-16
和2.44929e-16
转换为0
,从而生成此matrix3d:
The polyfill converts -2.44929e-16
and 2.44929e-16
to 0
thereby generating this matrix3d:
matrix3d(1、0、0、0、0、1、0、0、0、0、1、0、0、0、0、1)
matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)
增加polyfill代码中的小数精度可以解决此问题.将第35行从以下位置更改:
CSSMatrix.SMALL_NUMBER = 1e-6;
Increasing the decimal precision in the polyfill's code fixes this issue. Change line 35 from:
CSSMatrix.SMALL_NUMBER = 1e-6;
到
CSSMatrix.SMALL_NUMBER = 1e-20; // 20 decimal point precision
我已在此小提琴中修复了该问题.
I've fixed that in this fiddle.
关于注释中有关沿2轴旋转时生成不同矩阵的问题:这是因为小提琴中使用的compose
函数同时沿所有轴施加旋转-这等效于一个rotate3d(x, y, z)
调用.
Regarding the question in the comment about different matrices being generated when applying rotate along 2 axes: This is because the compose
function used in the fiddle applies rotation along all axes at the same time - which would be equivalent to a single rotate3d(x, y, z)
call.
但是通过CSS在小提琴中应用的变换分别在X和Z轴上旋转,这等效于先应用rotate(x, 0, 0)
然后是rotate(0, 0, z)
.
But the transforms applied via CSS in the fiddle rotate on the X and Z axes separately which would be equivalent to applying rotate(x, 0, 0)
followed by rotate(0, 0, z)
.
可以通过更改小提琴中的compose
函数,并将polyfill生成的matrix3d与浏览器生成的matrix3d进行比较来验证这一点.
This can be verified by changing the compose
function in the fiddle and comparing the matrix3d generated by the polyfill vs the one generated by the browser.
这篇关于Javascript:360度旋转和矩阵组成的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!