无法从特定方向旋转到另一个方向

4
我所提供的示例是使用CSS3变换和过渡的旋转动画立方体。
问题在于,在this jsfiddle的起始位置,似乎没有可能进行CSS3旋转以显示“4”面(向左旋转一次)。
JSFiddle的基本说明:按下“x”键使用CSS3“rotateX:90deg”样式化立方体,“y”表示rotateY,“z”表示rotateZ。单击“重置”按钮返回起始位置。注意*无论旋转(x、y或z),我都无法使立方体向左旋转一个位置。
我正在使用CSS3 rotate3d属性rotateX、rotateY和rotateZ,并使用CSS3过渡影响transform属性。
此外,值得一提的是,使用rotateX/Y/Z属性可以让立方体在几乎所有其他位置/方向上向上、向左、向右或向下旋转。

问题:

这里的问题是什么?旋转是否不可能?CSS3旋转存在问题还是我的代码/逻辑存在问题?

最佳答案将解释CSS3 rotate3d变换如何工作(幕后; 数学上)。


你尝试过使用箭头键代替“xyz”并使用负旋转吗? - bobthyasian
是的,原始项目使用箭头键,我尝试过使用-90度但没有成功。 - Justin McDonald
@JustinGingyMcDonald 我已经更新了我的答案,并提供了一个可行的解决方案。 - Asad Saeeduddin
2个回答

8
这里发生的变换是合成变换(即变换矩阵进行矩阵拼接)。例如,当您围绕元素的x轴旋转时,其他轴会旋转90度,使得围绕y轴的旋转不再产生最初的从右往左的效果。相反,它现在的行为类似于反转的z轴。请考虑以下图表:
多个变换应用到一个点上时,它们的所有变换矩阵都与该点本身相乘,并按照应用顺序从左到右进行矩阵乘法拼接。例如,假设90度绕x轴旋转的矩阵是Rx,90度绕y轴旋转的矩阵是Ry,90度绕z轴旋转的矩阵是Rz
假设我们按下了z两次并按下了x一次。现在,对于元素中的任何点P,它的新位置P'将被计算为:
P' = Rx . Rz . Rz . P
不幸的是,此方法的问题在于每个后续变换将应用于上一次计算结果得到的参考框架。因此,在这种情况下,当我们旋转它时,x轴将指向完全相反的方向。
解决此问题的方法(我不会涉及其数学)是以相反的顺序乘以矩阵。如果这样做,每个连续的变换将相对于固定轴而不是相对于之前的变换留下的任何状态进行。因此,我们的计算将如下所示:
P' = Rx . Rz . Rz . P
在对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' = Rnew . Rold . P

这样计算新的点向量相对于世界坐标而不是相对于变换后的坐标。

作为奖励,这也消除了全局变量的需要,因为元素的当前变换矩阵是我们需要的唯一信息。

简而言之

下面我包含了一个更新后的fiddle。按y键将您的立方体向右旋转90度。

这里是演示:http://jsfiddle.net/guruB/

(与以前一样,使用zxy绕相应的轴旋转)

注意:您可以在这里找到如何计算旋转矩阵的信息。


这太棒了。老实说,我惊呆了... 这个解决方案的细节、努力和范围超出了预期;你是这个社区的领袖之一。 - Justin McDonald
1
@JustinGingyMcDonald 哎呀,不过我还是对 MS Paint 魔方感到相当自豪的 :) - Asad Saeeduddin
你是大一新生?我不相信。 - Justin McDonald

-1

看一下这个演示

它使用以下代码向左旋转:

#cube.show-left {
      -webkit-transform: translateZ( -100px ) rotateY(   90deg );
         -moz-transform: translateZ( -100px ) rotateY(   90deg );
           -o-transform: translateZ( -100px ) rotateY(   90deg );
              transform: translateZ( -100px ) rotateY(   90deg );

问题在于我无法使用简单的旋转将立方体从演示中的起始位置转换为向左旋转一个角度。我需要这个简单的旋转,以便在用户将立方体沿x轴旋转3000度时,我可以使用这个简单的旋转来更改面。如果按照您的方式进行变换,立方体会在到达正确的面之前迅速反向旋转-3000度。 - Justin McDonald
你有没有想过将所有样式都写在CSS3中,然后使用Jquery应用这些样式呢? - bobthyasian
我就是这样做的,请查看fiddle。 - Justin McDonald
不是我想表达的意思,请看这个类似的帖子。将预设的过渡效果作为类,然后使用Jquery应用这些类。 - bobthyasian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接