Rotating CSS cube on fixed axes

Viewed 3322

I have a cube constructed using CSS. It's made of 6 faces and each face is transformed to form one face of the cube, and all the 6 faces are under one <div> with the class .cube. Any rotation I do to the cube is done on this enclosing cube class.

I want the cube to rotate based on mouse drag input. So far it kinda works. I just translate x and y mouse movement into cube rotation about the x and y axes.

But there's one major problem with this. I perform the rotation as a simple

transform: rotateX(xdeg) rotateY(ydeg)

CSS property. The issue with this is that the y axis of rotation is getting rotated with the x rotation.

Suppose I rotate the cube 90 degrees around the x axis. Now, if I try to rotate the cube 90 degrees along the y axis as well, I would expect the cube to rotate 90 degrees to the right or left (from my perspective). But instead, it's rotating about it's currently visible front face. That is, the y axis got rotated 90 degrees thanks to the x axis rotation that came first, and so now from the perspective of the user, it looks as if the cube is rotating around it's z axis.

I want to be able to rotate the cube in a way that the x y and z axes remain fixed from the perspective of the user. Also the cube needs to rotate from the current state in case the user lifts their finger off the button and clicks again and drags.

I've been finding this difficult to do. I feel this may not be possible using just the rotateX/Y/Z properties and instead I might have to use the 3d matrix or rotate3d properties?

I know this may not be the easiest thing to achieve using CSS but I still want to do it. Could someone point me in the right direction on how to solve this problem?

#cube-wrapper {
  position: absolute;
  left: 50%;
  top: 50%;
  perspective: 1500px;
}

.cube {
  position: relative;
  transform-style: preserve-3d;
}


/* Size and border color for each face */

.face {
  position: absolute;
  width: 200px;
  height: 200px;
  border: solid green 3px;
}


/* Transforming every face into their correct positions */

#front_face {
  transform: translateX(-100px) translateY(-100px) translateZ(100px);
}

#back_face {
  transform: translateX(-100px) translateY(-100px) translateZ(-100px);
}

#right_face {
  transform: translateY(-100px) rotateY(90deg);
}

#left_face {
  transform: translateY(-100px) translateX(-200px) rotateY(90deg);
}

#top_face {
  transform: translateX(-100px) translateY(-200px) rotateX(90deg);
}

#bottom_face {
  transform: translateX(-100px) rotateX(90deg);
}

.cube {
  transform: rotateX(90deg) rotateY(90deg);
}
<!-- Wrapper for the cube -->
<div id="cube-wrapper">
  <div class="cube">
    <!-- A div for each face of the cube -->
    <div id="front_face" class="face"></div>
    <div id="right_face" class="face"></div>
    <div id="back_face" class="face"></div>
    <div id="left_face" class="face"></div>
    <div id="top_face" class="face"></div>
    <div id="bottom_face" class="face"></div>
  </div>
</div>

I can't really add any javascript because I'm actually coding the logic in purescript. But the code just registers a mousedown handler that takes the current mouse x and y, compares it to the last x and y and accordingly rotates the cube around the x and y axes by changing the transform property of .cube with a value like.

  {transform: "rotateX(90deg) rotateY(90deg)"}
2 Answers
Related