这里发生的变换是复合变换(变换矩阵经历矩阵连接)。例如,当您围绕其 x 轴旋转元素时,其他轴将旋转 90 度,因此围绕 y 轴的旋转不再具有最初的从右到左的效果。相反,它现在的行为就像一个倒置的 z 轴。考虑下图:
问题背后的数学是这样的:当你对一个点应用多个变换时,它们的所有变换矩阵都与点本身相乘,按照应用的顺序从左到右。例如,让我们说绕 x 旋转 90 度的矩阵是 R x,绕 y 旋转 90 度的矩阵是 R y,绕 z 旋转 90 度的矩阵是 R z。
假设我们按z了两次和x一次。现在,对于元素中的任何点 P,其新位置 P '将计算为:
P ' = Rz 。Rz 。 _ R x 。磷
不幸的是,这样做的问题是每个后续转换都将应用于上次计算产生的参考系。所以在这种情况下,当我们围绕它旋转时,x 轴将指向完全相反的方向。
这个问题的解决方案(我不会讨论的数学问题)是将矩阵以相反的顺序相乘。如果这样做,每个连续的变换都将相对于固定轴,而不是相对于前一次变换离开轴的任何状态。所以我们的计算将如下所示:
P ' = R x 。Rz 。 _ Rz 。 _ 磷
在摆弄WebKitCSSMatrix
了一下之后,我设法提出了以下解决方案:
// Make a matrix out of the transformation currently in effect
var oldMatrix = new WebKitCSSMatrix(cube[0].style.webkitTransform);
//Make a matrix that applies the new rotation
var extraRotate = (new WebKitCSSMatrix()).rotate(anglex, angley, anglez);
//Multiply them (with the new one on the left)
var final = extraRotate.multiply(oldMatrix);
//I need to extract the elements of the final matrix into an array.
//They are stored like this: 1st row 1st column in key m11, 2nd row
//1st column in key m12, etc.
var finalstring = [];
for (var i = 1; i < 5; i++) {
for (var j = 1; j < 5; j++) {
finalstring.push(Math.round(final['m' + i + j]));
}
}
//Make a new style rule out of our final matrix and apply it to the element
cube[0].style.webkitTransform = 'matrix3d(' + finalstring.join(',') + ')';
通过将现有变换矩阵与所需的额外旋转预乘,这设法解决了旋转参考系的问题。请注意我如何首先计算extraRotate
矩阵,然后将其与现有转换相乘,有效地将矩阵以相反的应用顺序相乘:
P ' = R新 。旧 。 _ 磷
这会计算相对于世界坐标的新点向量,而不是相对于变换后的坐标。
作为奖励,这也消除了对全局变量的需要,因为元素的当前变换矩阵是我们需要的唯一信息。
TL;博士
我在下面包含了一个更新的小提琴。按下y
可将您的立方体向右旋转 90 度。
这是一个演示:http: //jsfiddle.net/guruB/
z(和以前一样,使用x和y围绕相应的轴旋转)
注意:您可以在此处了解如何计算旋转矩阵。