使用旋转和平移保持3D立方体边缘正确滚动的问题

10

请查看我的js Fiddle链接:https://jsfiddle.net/mauricederegt/5ozqg9uL/3/

var xAngle = 0;
var yAngle = 0;
var xPos  = 0;
var yPos  = 0;

$('body').keydown(function(evt) {
    if(evt.keyCode == 37) 
    {
        //left
        yAngle -= 90;
        xPos -= 100;
        //rotate and translate the position of the cube
        $('#cube')[0].style["WebkitTransform"] = "translateX("+xPos+"px) translateY("+yPos+"px) rotateX(" + xAngle + "deg) rotateY(" + yAngle + "deg)";
    }
    if(evt.keyCode == 39) 
    {
        //right
        yAngle -= -90;
        xPos -= -100;
        //rotate and translate the position of the cube
        $('#cube')[0].style["WebkitTransform"] = "translateX("+xPos+"px) translateY("+yPos+"px) rotateX(" + xAngle + "deg) rotateY(" + yAngle + "deg)";
    }
    if(evt.keyCode == 38) 
    {
        //up
        xAngle -= -90;
        yPos -= 100;
        //rotate and translate the position of the cube
        $('#cube')[0].style["WebkitTransform"] = "translateX("+xPos+"px) translateY("+yPos+"px) rotateX(" + xAngle + "deg) rotateY(" + yAngle + "deg)";
    }
    if(evt.keyCode == 40) 
    {
        //down
        xAngle -= 90;
        yPos -= -100;
        //rotate and translate the position of the cube
        $('#cube')[0].style["WebkitTransform"] = "translateX("+xPos+"px) translateY("+yPos+"px) rotateX(" + xAngle + "deg) rotateY(" + yAngle + "deg)";
    }
});
#scene {
    padding: 10px;
    -webkit-perspective: 800;
}

#cube {
    position: relative;
    padding-top: 0;
    margin: 0 auto;
    height: 100px;
    width: 100px;
    -webkit-transition: -webkit-transform 0.4s linear;
    -webkit-transform-style: preserve-3d;

   
}

.face {
    position: absolute;
    height: 85px;
    width: 85px;
    border-style: solid;
    border-width: 5px;
    border-color: grey;
    padding: 5px;
    background-color: rgba(190, 190, 190, 0.7);
}

#cube .one  {
    -webkit-transform: rotateX(90deg) translateZ(50px);
}

#cube .two {
    -webkit-transform: translateZ(50px);
}

#cube .three {
    -webkit-transform: rotateY(90deg) translateZ(50px);
}

#cube .four {
    -webkit-transform: rotateY(180deg) translateZ(50px);
}

#cube .five {
    -webkit-transform: rotateY(-90deg) translateZ(50px);
}

#cube .six {
    -webkit-transform: rotateX(-90deg) translateZ(50px) rotate(180deg);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!doctype html>
<html>
<body>
<div id="scene">
    Press the arrow keys...
    <div id="cube">
        <div class="face one">
            Face 1
        </div>
        <div class="face two">
            Face 2
        </div>
        <div class="face three">
            Face 3
        </div>
        <div class="face four">
            Face 4
        </div>
        <div class="face five">
            Face 5
        </div>
        <div class="face six">
            Face 6
        </div>
    </div>
</div>
</body>
</html>

你可以看到我有一个CSS3 3D立方体,您可以使用箭头键移动它。您可以将其向左、向右、向上和向下移动。为了实现这一点,我在各种变量中存储位置和角度:

var xAngle = 0;
var yAngle = 0;
var xPos  = 0;
var yPos  = 0;

这个立方体在上下滚动时总是“正确滚动”,但左右滚动并非总是如此。

例子:

  1. 初始状态按左箭头键,然后按右箭头键任意次数。立方体的行为是正确的。
  2. 现在按下一次下箭头,再按两次左箭头(或右箭头), 立方体就会不正确地滚动。
  3. 但是,如果你再次按向上或向下的箭头键,它就能再次正确地上下滚动了。

因此,这个问题只似乎存在于左右滚动中。我该怎么解决这个问题?


1
如果你仔细观察左/右键触发时,无论显示哪个面,它们都会在同一枢轴点上旋转。例如...魔方从第2面开始,当你向右转时,它会在第6面上旋转。现在向下再向左转,同样,它在第6面上旋转。再向下到第4面(倒置),它仍然在第6面上旋转...我认为这很可能是代码的默认行为... - dale landry
如果在向左或向右移动时先旋转 y 再旋转 x,它会稍微靠近一点。只有当您更改轴时才会出现问题。 - Steve0
1
如果你想让立方体始终具有相同的“滚动”-“枢轴”行为,当你按下左键时底部面围绕水平轴旋转,那么你可能需要编写代码,以便在事件触发时找到实际粘着在枢轴上的面... - dale landry
我明白你们在说枢轴的问题,但我不知道该如何解决。在谷歌上搜索了一下,但没有找到有用的信息。而且我不明白为什么它不会影响上下滚动?任何帮助都将不胜感激。 - Maurice
2个回答

3

你需要考虑三种旋转,代表着三个不同的轴,而不是像你现在做的那样只有两个。

这是更新过的代码版本。请注意,我根据其他轴的角度来更新某个轴的角度。

尽管我发现了一些奇怪的运动(可能是我错过的一些边缘情况),但这是一个良好的起点,仍不是一个完美的解决方案。

var xAngle = 0;
var yAngle = 0;
var zAngle = 0;
var xPos = 0;
var yPos = 0;

$('body').keydown(function(evt) {
  if (evt.keyCode == 37) {
    //left
    if (xAngle % 180 == 0)
      yAngle -= 90;
    else
      zAngle -= 90;
    xPos -= 100;
  }
  if (evt.keyCode == 39) {
    //right
    if (xAngle % 180 == 0)
      yAngle -= -90;
    else
      zAngle -= -90;

    xPos -= -100;
  }
  if (evt.keyCode == 38) {
    //up
    if (yAngle % 180 == 0)
      xAngle -= -90;
    else
      zAngle -= -90;
    yPos -= 100;
  }
  if (evt.keyCode == 40) {
    //down
    if (yAngle % 180 == 0)
      xAngle -= 90;
    else
      zAngle -= 90;
    yPos -= -100;
  }
  $('#cube').css('transform', "translateX(" + xPos + "px) translateY(" + yPos + "px) rotateX(" + xAngle + "deg) rotateY(" + yAngle + "deg) rotateZ(" + zAngle + "deg)");
});
#scene {
  padding: 10px;
  perspective: 800;
}

#cube {
  position: relative;
  padding-top: 0;
  margin: 0 auto;
  height: 100px;
  width: 100px;
  transition: transform 0.4s linear;
  transform-style: preserve-3d;
}

.face {
  position: absolute;
  height: 85px;
  width: 85px;
  border-style: solid;
  border-width: 5px;
  border-color: grey;
  padding: 5px;
  background-color: rgba(190, 190, 190, 0.7);
}

#cube .one {
  transform: rotateX(90deg) translateZ(50px);
}

#cube .two {
  transform: translateZ(50px);
}

#cube .three {
  transform: rotateY(90deg) translateZ(50px);
}

#cube .four {
  transform: rotateY(180deg) translateZ(50px);
}

#cube .five {
  transform: rotateY(-90deg) translateZ(50px);
}

#cube .six {
  transform: rotateX(-90deg) translateZ(50px) rotate(180deg);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="scene">
  Press the arrow keys...
  <div id="cube">
    <div class="face one">
      Face 1
    </div>
    <div class="face two">
      Face 2
    </div>
    <div class="face three">
      Face 3
    </div>
    <div class="face four">
      Face 4
    </div>
    <div class="face five">
      Face 5
    </div>
    <div class="face six">
      Face 6
    </div>
  </div>
</div>


啊,Z轴!感谢这个例子,我会试着玩一下,看看能否解决其中的问题。谢谢。 - Maurice

-1

看起来你的问题是翻译都相对于原始方向进行,而你没有考虑到每次旋转中正x、y坐标不同的事实。


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