Infinite 360 deg 3d rotation of an isometric shape with nested hover animation

Viewed 227

I try to understand how to animate a 3d object with css. Right now i have an isometric type of shape that shows its inside when it's hovered. But additionally i want to animate this isometric shape to turn around 360deg as 3d shape infinite. I've been fiddling with its transform for each box but it doesn't work at all.

Can anyone help me and give some tips or explanations how i can achieve this?

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.cube {
  width: 100px;
  height: 150px;
  position: absolute;
  background-color: red;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  margin: 50% auto;
}

.outterstack .left {
  min-width: 100px;
  min-height: 250px;
  transform-origin: 0 0;
  transform: rotate(90deg) skewX(-30deg) scaleY(0.864);
  background-color: grey;
}

.outterstack .right {
  min-height: 100px;
  min-width: 250px;
  transform-origin: 0 0;
  transform: rotate(-30deg) skewX(-30deg) scaleY(0.864);
  position: relative;
  bottom: 250px;
  background-color: grey;
}

.outterstack .up {
  width: 250px;
  height: 250px;
  transform-origin: 0 0;
  transform: rotate(210deg) skew(-30deg) scaleY(0.864);
  position: relative;
  bottom: 350px;
  background-color: violet;
}

.insidestack .left {
  min-width: 50px;
  min-height: 150px;
  transform-origin: 0 0;
  transform: rotate(90deg) skewX(-30deg) scaleY(0.864);
  background-color: black;
}

.insidestack .right {
  min-height: 100px;
  min-width: 150px;
  transform-origin: 0 0;
  transform: rotate(-30deg) skewX(-30deg) scaleY(0.864);
  position: relative;
  bottom: 149px;
  background-color: yellow;
}

.insidestack .up {
  width: 150px;
  height: 150px;
  transform-origin: 0 0;
  transform: rotate(210deg) skew(-30deg) scaleY(0.864);
  position: relative;
  bottom: 249px;
  background-color: green;
}

.one,
.two,
.three,
.oneins,
.twoins,
.threeins,
.four {
  position: relative;
  left: 150px;
  transition: 1s;
}

.one {
  top: 150px;
  z-index: 7;
}

.oneins {
  bottom: 400px;
  z-index: 1;
}

.two {
  bottom: 740px;
  z-index: 5;
}

.twoins {
  bottom: 1200px;
  z-index: 1;
}

.three {
  bottom: 1630px;
  z-index: 3;
}

.threeins {
  bottom: 2120px;
  z-index: 1;
}

.four {
  bottom: 2520px;
  z-index: 1;
}

.cube:hover .one {
  top: 150px;
  z-index: 7;
}

.cube:hover .oneins {
  bottom: 400px;
  z-index: 6;
}

.cube:hover .two {
  bottom: 650px;
  z-index: 5;
}

.cube:hover .twoins {
  bottom: 1200px;
  z-index: 4;
}

.cube:hover .three {
  bottom: 1450px;
  z-index: 3;
}

.cube:hover .threeins {
  bottom: 2000px;
  z-index: 2;
}

.cube:hover .four {
  bottom: 2250px;
  z-index: 1;
}
<div class="cube">
  <div class="outterstack one">
    <div class="left"></div>
    <div class="right"></div>
    <div class="up"></div>
  </div>
  <div class="insidestack oneins">
    <div class="left"></div>
    <div class="right"></div>
    <div class="up"></div>
  </div>
  <div class="outterstack two">
    <div class="left"></div>
    <div class="right"></div>
    <div class="up"></div>
  </div>
  <div class="insidestack twoins">
    <div class="left"></div>
    <div class="right"></div>
    <div class="up"></div>
  </div>
  <div class="outterstack three">
    <div class="left"></div>
    <div class="right"></div>
    <div class="up"></div>
  </div>
  <div class="insidestack threeins">
    <div class="left"></div>
    <div class="right"></div>
    <div class="up"></div>
  </div>
  <div class="outterstack four">
    <div class="left"></div>
    <div class="right"></div>
    <div class="up"></div>
  </div>
</div>

2 Answers

You can do this with an css @keyframes animation, but then you need two more side surfaces for each cuboid. Instead the 'up' surfaces from the inner cuboids are not necessary since they are not visible.

Working example:

.cube {
  position: absolute;
  top: 0;
  left: 100px;
  width: 250px;
  height: 250px;
  margin: 50px auto;
  transform-style: preserve-3d;
  animation-name: example;
  animation-duration: 8s;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
}

@keyframes example {
  0% {
    transform: rotateX(-17deg) rotate3d(0, 1, 0, 0deg);
  }
  100% {
    transform: rotateX(-17deg) rotate3d(0, 1, 0, 360deg);
  }
}

.insidestack {
  margin-left: 50px;
}


                                   /* positioning of the cuboids */
.outterstack,
.insidestack {
  position: relative;
  transition: top 1s;
}

.one {
  top: 0;
}

.oneins {
  top: 5px;
}

.two {
  top: 110px;
}

.twoins {
  top: 115px;
}

.three {
  top: 220px;
}

.threeins {
  top: 225px;
}

.four {
  top: 330px;
}


                                   /* positioning when hovered */
.cube:hover .oneins {
  top: 105px;
}

.cube:hover .two {
  top: 210px;
}

.cube:hover .twoins {
  top: 315px;
}

.cube:hover .three {
  top: 420px;
}

.cube:hover .threeins {
  top: 525px;
}

.cube:hover .four {
  top: 630px;
}


                                   /* positioning of the surfaces */
.side,
.flat {
  position: absolute;
}

.outterstack .front {
  transform: translateZ(125px);
}

.outterstack .back {
  transform: rotateY(180deg) translateZ(125px);
}

.outterstack .right {
  transform: rotateY(90deg) translateZ(125px);
}

.outterstack .left {
  transform: rotateY(-90deg) translateZ(125px);
}

.outterstack .up {
  transform: rotateX(90deg) translateZ(125px);
}

.insidestack .front {
  transform: translateZ(75px);
}

.insidestack .back {
  transform: rotateY(180deg) translateZ(75px);
}

.insidestack .right {
  transform: rotateY(90deg) translateZ(75px);
}

.insidestack .left {
  transform: rotateY(-90deg) translateZ(75px);
}


                                   /* styling of the surfaces */
.outterstack .side {
  width: 250px;
  height: 100px;
  border: 1px solid black;
  background-color: grey;
}

.outterstack .flat {
  width: 250px;
  height: 250px;
  background-color: violet;
}

.insidestack .side {
  width: 150px;
  height: 100px;
}

.insidestack .front,
.insidestack .back {
  background-color: yellow;
}

.insidestack .right,
.insidestack .left {
  background-color: black;
}
<div class="cube">
  <div class="outterstack one">
    <div class="side front"></div>
    <div class="side back"></div>
    <div class="side right"></div>
    <div class="side left"></div>
    <div class="flat up"></div>
  </div>
  <div class="insidestack oneins">
    <div class="side front"></div>
    <div class="side back"></div>
    <div class="side right"></div>
    <div class="side left"></div>
  </div>
  <div class="outterstack two">
    <div class="side front"></div>
    <div class="side back"></div>
    <div class="side right"></div>
    <div class="side left"></div>
    <div class="flat up"></div>
  </div>
  <div class="insidestack twoins">
    <div class="side front"></div>
    <div class="side back"></div>
    <div class="side right"></div>
    <div class="side left"></div>
  </div>
  <div class="outterstack three">
    <div class="side front"></div>
    <div class="side back"></div>
    <div class="side right"></div>
    <div class="side left"></div>
    <div class="flat up"></div>
  </div>
  <div class="insidestack threeins">
    <div class="side front"></div>
    <div class="side back"></div>
    <div class="side right"></div>
    <div class="side left"></div>
  </div>
  <div class="outterstack four">
    <div class="side front"></div>
    <div class="side back"></div>
    <div class="side right"></div>
    <div class="side left"></div>
    <div class="flat up"></div>
  </div>
</div>

take a look at my code. i hope this helps you understand cube rotation.

var current = 0;
var interval = setInterval(function() {}, 1000);
function rotateX() {
  clearInterval(interval);
  interval = setInterval(function() {
    current++;
    document.getElementById("cube").style.transform = "rotate3d(1, 0, 0, "+current+"deg)";
    
    if (current > 360) {
      current = 0;
    }
  }, 30);
}
function rotateY() {
  clearInterval(interval);
  interval = setInterval(function() {
    current++;
    document.getElementById("cube").style.transform = "rotate3d(0, 1, 0, "+current+"deg)";
    
    if (current > 360) {
      current = 0;
    }
  }, 30);
}
function rotateZ() {
  clearInterval(interval);
  interval = setInterval(function() {
    current++;
    document.getElementById("cube").style.transform = "rotate3d(0, 0, 1, "+current+"deg)";
    
    if (current > 360) {
      current = 0;
    }
  }, 30);
}
rotateX();
#cube {
    width: 100px;
    height: 100px;
    transform-style: preserve-3d;
}
.side {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    position: absolute;
    backface-visibility: inherit;
    font-size: 14px;
    color: #fff;
}
.front {
    background: rgba(90,90,90,.7);
    transform: translateZ(50px);
}
.back {
    background: rgba(0,210,0,.7);
    transform: rotateY(180deg) translateZ(50px);
}
.right {
    background: rgba(210,0,0,.7);
    transform: rotateY(90deg) translateZ(50px);
}
.left {
    background: rgba(0,0,210,.7);
    transform: rotateY(-90deg) translateZ(50px);
}
.top {
    background: rgba(210,210,0,.7);
    transform: rotateX(90deg) translateZ(50px);
}
.bottom {
    background: rgba(210,0,210,.7);
    transform: rotateX(-90deg) translateZ(50px);
}
<div id="cube" class="transition-all" style="transform: rotate3d(0, 1, 1, 45deg);">
  <div class="side front">front</div>
  <div class="side back">back</div>
  <div class="side right">right</div>
  <div class="side left">left</div>
  <div class="side top">top</div>
  <div class="side bottom">bottom</div>
</div>

<div style="margin-top: 50px">
<button onclick="rotateX()">rotate X</button>
<button onclick="rotateY()">rotate Y</button>
<button onclick="rotateZ()">rotate Z</button>
</div>

Related