为什么我的3D立方体旋转不如预期?

7

我正在做一个3D骰子,当你滑动它的面时它会旋转。问题是在某些情况下它表现得非常奇怪。例如,如果你运行代码段并向左滑动两次然后向下滑动,它会进行疯狂的旋转...

以下是代码:

$(function() {
  
  var X = 0,
    Y = 0;
  
  var hammertime = new Hammer($(".thirdDimension")[0], {domEvents: true});
  
  hammertime.get('swipe').set({ direction: Hammer.DIRECTION_ALL });
  
  function rotate(what) {
    switch (what) {
      case "X":
        $(".cube").css("transform", "rotateX(" + X + "deg) rotateY(" + Y +"deg)");
        break;
      case "Y":
        $(".cube").css("transform", "rotateY(" + Y +"deg) rotateX(" + X + "deg)");
        break;
    }
    $("#debug").html($("#debug").html() + $(".cube").attr("style") + "<br>").scrollTop($("#debug")[0].scrollHeight);
  }
  
  $(".thirdDimension").on("swipeleft", function(e){
    Y -= 90;
    rotate("Y");
  });

  $(".thirdDimension").on("swiperight", function(e){
    Y += 90;
    rotate("Y");
  });
  
  $(".thirdDimension").on("swipeup", function(e){
    X += 90;
    rotate("X");
  });
  
  $(".thirdDimension").on("swipedown", function(e){
    X -= 90;
    rotate("X");
  });
  
});
* {
  box-sizing: border-box;
}
html, body {
  height: 100%;
  font-family: sans-serif;
}
.tableContainer, .vcenter {
  height: 100%;
  width: 100%;
}
.tableContainer {
  display: table;
}
.vcenter {
  height: 100%;
  display: table-cell;
  vertical-align: middle;
}
.thirdDimension {
  perspective: 500px;
 perspective-origin: 50% 100px;
}
.cube {
  margin: 0 auto;
  position: relative;
 width: 200px;
  height: 200px;
 transform-style: preserve-3d;
}
.cube div {
 position: absolute;
 width: 200px;
 height: 200px;
  box-shadow: inset 0 0 30px black;
  font-size: 72pt;
  padding-top: 35px;
  text-align: center;
  background-color: black;
}

.right {
  transform: rotateY(-270deg) translateX(100px);
 transform-origin: top right;
}
.left {
 transform: rotateY(270deg) translateX(-100px);
 transform-origin: center left;
}
.up {
 transform: rotateX(90deg) translateY(-100px);
 transform-origin: top center;
}
.down {
 transform: rotateX(-90deg) translateY(100px);
 transform-origin: bottom center;
}
.front {
 transform: translateZ(100px);
}
.back {
 transform: translateZ(-100px) rotateY(180deg);
}
.cube {
  -webkit-transition: .3s all linear;
  cursor: pointer;
}
.cube div:after {
  display: block;
  position: absolute;
  width: 100px;
  height: 100px;
  content: "";
  border: 1px solid;
}
.front:after {
  top: 0;
  right: 0;
  background-color: green;
}
.back:after {
  bottom: 0;
  right: 0;
  background-color: blue;
}
.right:after {
  top: 0;
  left: 0;
  background-color: red;
}
.left:after {
  bottom: 0;
  left: 0;
  background-color: DarkOrange;
}
.up:after {
  right: 0;
  bottom: 0;
  background-color: white;
}
.down:after {
  bottom: 0;
  left: 0;
  background-color: yellow;
}
#debug {
  position: fixed;
  background-color: cyan;
  overflow: auto;
  height: 50px;
  width: 100%;
}
/*
.cube {
  animation: linear 5s rotate infinite;
}
@-webkit-keyframes rotate {
  0% {
    transform: rotateX(0deg) rotateY(0deg);
  }
  100% {
    transform: rotateX(360deg) rotateY(720deg);
  }
}
*/
<script src="https://cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.8/hammer.min.js"></script>
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<div id='debug'></div>
<div class='tableContainer'>
  <div class='vcenter'>
    <div class='thirdDimension'>
      <div class='cube'>
        <div class='up'></div>
        <div class='front'></div>
        <div class='right'></div>
        <div class='left'></div>
        <div class='back'></div>
        <div class='down'></div>
      </div>
    </div>
  </div>
</div>

编辑: 这个链接:http://greensock.com/forums/topic/7811-3d-rotation-fixed-axsis/ 说旋转的顺序很重要。我稍微改了我的代码,但仍然无法预料地旋转...


1
"var hammertime = new Hammer" 让我忍不住笑了。 - Woodrow Barlow
@WoodrowBarlow 我刚从文档中获取了这个信息... - Filipe Teixeira
2个回答

4

首先:不同的 "X""Y" 转换设置导致了巨大的旋转。我将它们都更改为:

$(".cube").css("transform", "rotateX(" + X + "deg) rotateY(" + Y +"deg)");

如果您希望魔方始终沿着滑动的方向旋转,请继续阅读。如果不需要,请更改上述代码即可。
其次,当您旋转魔方时,您正在改变其方向。X轴永远不会出错,但是您很难注意到Y轴和Z轴在交换。
现在,您可以将rotateZ添加到混合中:
$(".cube").css("transform", "rotateX(" + X + "deg) rotateY(" + Y +"deg) rotateZ(" + Z + "deg)");

我已经在这里改变了代码,以提供一个例子。 我还没有完成它,因为我已经发现了问题,但是没有时间完善它。

$(function() {

    var X = 0,
      Y = 0,
      Z = 0;

    var hammertime = new Hammer($(".thirdDimension")[0], {domEvents: true});

  hammertime.get('swipe').set({ direction: Hammer.DIRECTION_ALL });

  function rotate() {
      $(".cube").css("transform", "rotateX(" + X + "deg) rotateY(" + Y +"deg) rotateZ(" + Z + "deg)");
      $("#debug").html($("#debug").html() + $(".cube").attr("style") + "<br>").scrollTop($("#debug")[0].scrollHeight);
  }

  $(".thirdDimension").on("swipeleft", function(e){
      //Y -= 90;
      check(-90);
      rotate();
  });

  $(".thirdDimension").on("swiperight", function(e){
      //Y += 90;
    check(90);
    rotate();
  });

  $(".thirdDimension").on("swipeup", function(e){
      X += 90;
      rotate();
  });

  $(".thirdDimension").on("swipedown", function(e){
      X -= 90;
      rotate();
  });

  function check(num) {
      var temp = Math.abs(X % 360);
          switch (temp) {
              case 0:
                  console.log(temp);
                  Y += num;
                  break;
              case 90:
                  console.log(temp);
                  Z -= num
                  break;
              case 180:
                  console.log(temp);
                  Y -= num;
                  break;
             case 270:
                 console.log(temp);
                 Z -= num;
                 break;
          }
    }

});

您需要检查y轴(Math.abs(Y % 360))),可能还需要检查z轴,并相应地旋转y轴和z轴(+-90)。

这个方法大部分情况下是有效的,但需要在确定正确的轴线旋转方向上进行微调。祝好运。


感谢您的合作,但是您的CodePen显示404错误。我尝试将更改复制到我的演示中,但没有成功。据我所知,问题出在Y轴上,而不是X轴。 - Filipe Teixeira
1
更新了笔链接,抱歉。 - theblindprophet

3
您的问题更多地涉及到您对旋转的概念化,而不是任何编码错误。
如果您先执行rotateY(90),然后执行rotateX(90) - 那么在您执行rotateX(90)时,您的X轴已经旋转了90度,因此它不再是从左到右,而是垂直于屏幕。所以在这种情况下,您的物体看起来像是在进行2D旋转。
并且更进一步,如果用户现在从左向右滑动,则实际上是沿着Z轴滑动,您需要旋转Z轴。
要解决这个问题,您需要跟踪您所做的旋转,并以更动态的方式将用户界面映射到立方体中。从左向右滑动并不总是意味着要旋转Y轴,而是意味着沿当前朝向左右的轴旋转。 我建议您找一个魔方或类似的东西,按轴标记各个面(例如,红色面是X轴),模拟滑动,那么这样应该会更清晰,因为您会看到这些轴在魔方上移动。

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