如何在此动画中使侧面元素在x轴上旋转?

时间:2014-08-21 22:26:03

标签: javascript css3 animation greensock tweenlite

我正在尝试构建一个旋转的立方体动画,其侧面也会在各自的轴上旋转。这就是我到目前为止所拥有的:

http://codepen.io/Chevex/pen/pxtwj

以下CSS规则控制每个动画前面的位置:

.front {
  transform: translateZ(100px);
  background-color: #0f0;
}
.back {
  transform: rotateY(180deg) translateZ(100px);
  background-color: #f00;
}
.right {
  transform: rotateY(90deg) translateZ(100px);
  background-color: #00f;
}
.left {
  transform: rotateY(-90deg) translateZ(100px);
  background-color: #ff0;
}
.top {
  transform: rotateX(90deg) translateZ(100px);
  background-color: #0ff;
}
.bottom {
  transform: rotateX(-90deg) translateZ(100px);
  background-color: #f0f;
}

这很有效并且相应地定位元素。接下来,我使用GSAP animation library旋转整个多维数据集:

TweenMax.to($('.cube'), 7, { rotationY: 360, repeat: -1, ease: Linear.easeNone });

之后,我为前后两侧设置动画,使它们相对于Z轴旋转:

TweenMax.to($('.front, .back'), 2, { rotationZ: 360, repeat: -1, ease: Linear.easeNone });

接下来是Y轴的顶部和底部:

TweenMax.to($('.top, .bottom'), 2, { rotationY: 360, repeat: -1, ease: Linear.easeNone });

到目前为止一切顺利。现在左右两侧需要在X轴上旋转:

TweenMax.to($('.right, .left'), 2, { rotationX: 360, repeat: -1, ease: Linear.easeNone });

现在有一个问题。由于某种原因,它们似乎在Z轴上旋转。我试过在所有3轴上旋转它们但它们似乎从来没有像滚动硬币一样旋转,就像其他方面做得很好。我认为这是一个GSAP错误,但我手动将以下CSS动画应用于这些方面,并且存在同样的问题。

.right {
  transform: rotateY(90deg) translateZ(100px);
  background-color: #00f;
  -webkit-animation: spinRight 2s linear infinite;
}
.left {
  transform: rotateY(-90deg) translateZ(100px);
  background-color: #ff0;
  -webkit-animation: spinLeft 2s linear infinite;
}

@-webkit-keyframes spinRight {
  from {
    transform: rotateY(90deg) translateZ(100px) rotateX(0deg);
  }
  to {
    transform: rotateY(90deg) translateZ(100px) rotateX(360deg);
  }
}

@-webkit-keyframes spinLeft {
  from {
    transform: rotateY(-90deg) translateZ(100px) rotateX(0deg);
  }
  to {
    transform: rotateY(-90deg) translateZ(100px) rotateX(360deg);
  }
}

为什么会这样?如何让立方体的左侧和右侧以其他所有方式旋转的方式旋转?

1 个答案:

答案 0 :(得分:3)

是的,你是gimbal locked,需要在rotateY之前放置rotateX值。顺序对变换非常重要。

在您的情况下会发生的是90度(正或负)Y旋转将X轴旋转到Z(或-Z轴)。通常当你拥有全部3时,排序X,Y和Z将使X保持平直,但是当Y为+/- 90或270时,Z将会进行万向节锁定。通过将Y放在Y之后,您将其旋转到Z中轴(在那个排序中它是'在'Y轴内)。

试试这个:

@-webkit-keyframes spinRight {
  from {
    transform: rotateX(0deg) rotateY(90deg) translateZ(100px);
  }
  to {
    transform: rotateX(360deg) rotateY(90deg) translateZ(100px);
  }
}

@-webkit-keyframes spinLeft {
  from {
    transform: rotateX(0deg) rotateY(-90deg) translateZ(100px);
  }
  to {
    transform: rotateX(360deg) rotateY(-90deg) translateZ(100px);
  }
}

如果这不能解决问题,请尝试嵌套div并旋转div的Z轴。 CSS具有有限的3d能力,因为万向节锁定是一个巨大的问题。此外,由于360度正弦和余弦波周期,rotate3d受到限制(与确定矩阵的数学有关)。对于矩阵数学Sylvester有效,或者您可以查看three.js哪些有自己的功能来处理上述限制(我相信Google使用了三个用于其Rubik&#s立方体涂鸦)。


来自问题作者编辑:

这个答案是对的。 Greensock人们希望我将我的边元素嵌套在父元素中并修改父元素的轴。这可能有效,但我最初的尝试只是引起了其他问题。在Gimbal Lock上读了一下后,我意识到它正在修改轴的方式导致锁定。我有一个想法到达相同的位置,但通过以不同的方式操纵轴。它起作用了,这就是结果:

http://codepen.io/Chevex/pen/pxtwj

而不是:

TweenMax.set('.right', { rotationY: 90, x: '100px' });
TweenMax.set('.left', { rotationY: -90, x: '100px' });

我坐下来跟着我的脑袋走了一条轴,然后想出了一条新的路径让元素到达同一个地方。

TweenMax.set('.right', { rotationZ: 90, rotationY: 90, rotationX: 90, x: '100px' });
TweenMax.set('.left', { rotationZ: -90, rotationY: -90, rotationX: 90, x: '100px' });

之后,我能够为Y轴设置动画并获得预期结果,因为Y轴指向我最初预期X轴指向的方向。

TweenMax.to('.right, .left', gearSpeed, { rotationY: 360, repeat: -1, ease: Linear.easeNone });