Анимация граней на изометрическом кубе CSS

Я пытаюсь анимировать грани изометрического куба, который я создал, используя преобразования CSS, чтобы создать эффект «распаковки / разворачивания».

Я хочу, чтобы крышка куба вращалась вверх, но в данный момент она отплывает, а не вращается от края. Анимация начинается и заканчивается в нужных местах. Я пробовал изменить свойство transform-origin, но это не помогло. Вот мой код:

html body {
  position: relative;
  height: 100vh;
  width: 100vw;
  background-color: #C4C5C4;
}

.front,
.back {
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  position: absolute;
}

.front {
  z-index: 99;
}

.cube {
  transform-style: preserve-3d;
  transform: rotateX(-35deg) rotateY(45deg);
}

.face {
  position: absolute;
  width: 30vh;
  height: 30vh;
  background: white;
  border: solid 1px blue;
}

.top {
  transform-origin: 100% 100%;
  transform: rotateX(90deg) rotateY(0deg) translate3d(15vh, 0, 15vh);
  animation: rotatelid 5s linear infinite alternate;
}

.frontleft {
  transform: rotateY(-90deg) translate3d(0, 0, 15vh);
}

.frontright {
  transform: translate3d(0, 0, 15vh);
}

.backleft {
  transform: translate3d(0, 0, -15vh);
  background: lightgrey;
}

.backright {
  transform: rotateY(-90deg) translate3d(0, 0, -15vh);
}

@keyframes rotatelid {
  from {
    transform: rotateX(90deg) rotateY(0deg) translate3d(15vh, 0, 15vh);
  }

  to {
    transform: rotateX(90deg) rotateY(90deg) translate3d(-15vh, 0vh, 15vh);
  }
}
<div class='front'>
  <div class='cube'>
    <div class='face top'></div>
    <div class='face frontleft'></div>
    <div class='face frontright'></div>
  </div>
</div>

<div class='back'>
  <div class='cube'>
    <div class='face backleft'></div>
    <div class='face backright'></div>
  </div>
</div>

Кто-нибудь знает, как решить эту проблему, и есть ли лучший способ создавать простые анимации в Интернете (возможно, с использованием SVG?).

Свободный перевод вопроса Animating faces on a CSS isometric cube от участника @wrgt.


Ответы (2 шт):

Автор решения: Alexandr_TT

Обновите порядок преобразования, чтобы сначала подвинуть (translate) элемент, а затем повернуть его. Обратите внимание на translate, потому что он уже не тот, что был добавлен первым.

html body {
  position: relative;
  height: 100vh;
  margin:0;
  background-color: #C4C5C4;
}

.front,
.back {
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  position: absolute;
}

.front {
  z-index: 99;
}

.cube {
  transform-style: preserve-3d;
  transform: rotateX(-35deg) rotateY(45deg);
}

.face {
  position: absolute;
  width: 30vh;
  height: 30vh;
  background: white;
  border: solid 1px blue;
  box-sizing:border-box;
}

.top {
  transform-origin: 100% 100%;
  transform: translate3d(15vh, -15vh, 0vh) rotateX(90deg) rotateY(0deg);
  animation: rotatelid 5s linear infinite alternate;
}

.frontleft {
  transform: rotateY(-90deg) translate3d(0, 0, 15vh);
}

.frontright {
  transform: translate3d(0, 0, 15vh);
}

.backleft {
  transform: translate3d(0, 0, -15vh);
  background: lightgrey;
}

.backright {
  transform: rotateY(-90deg) translate3d(0, 0, -15vh);
}

@keyframes rotatelid {
  from {
    transform:translate3d(15vh, -15vh, 0vh) rotateX(90deg) rotateY(0deg);
  }

  to {
    transform:translate3d(15vh, -15vh, 0vh) rotateX(90deg) rotateY(90deg);
  }
}
<div class='front'>
  <div class='cube'>
    <div class='face top'></div>
    <div class='face frontleft'></div>
    <div class='face frontright'></div>
  </div>
</div>

<div class='back'>
  <div class='cube'>
    <div class='face backleft'></div>
    <div class='face backright'></div>
  </div>
</div>

Свободный перевод ответа от участника @Temani Afif.

→ Ссылка
Автор решения: Sevastopol'

А-ля презентация stackoverflow)

document.querySelector("#cube").onclick = function() {
  this.classList.toggle("open");
  window.setTimeout(function() {
    document.querySelector(".stack").classList.toggle("stack__active");
  }, 300);
}
* {margin: 0; padding: 0; box-sizing: border-box;}
body {min-height: 100vh; display: flex; align-items: center;}

.container {
  position: relative; width: 600px; height: 600px; margin: auto; perspective: 1200px;
}
.transform {transform: rotateX(-37.4deg); transform-style: preserve-3d;}

#cube {
  position: absolute; width: 200px; height: 200px; margin: 200px;
  transform: rotateY(45deg); transform-style: preserve-3d; transform-origin: center center; cursor: pointer;
}

.cube {
  position: absolute; width: 200px; height: 200px;
  border: 1px solid gray; background: rgba(0, 0, 0, 0.9);
  transition: all .5s ease-out;
}

.front {transform: rotateY(0deg) translateZ(100px);}
.back {transform: rotateX(180deg) translateZ(100px);}
.top {transform: rotateX(90deg) translateZ(100px);}
.left {transform: rotateY(-90deg) translateZ(100px);}
.right {transform: rotateY(90deg) translateZ(100px);}
.bottom {transform: rotateX(-90deg) translateZ(100px);}

#cube.open .front {transform: rotateY(0deg) translateZ(200px);}
#cube.open .top {transform: rotateX(90deg) translateZ(200px);}
#cube.open .left {transform: rotateY(-90deg) translateZ(200px);}

.stack {
  position: absolute; top: 20px; left: 70px; width: 70px; height: 100px;
  background-image: url(https://cdn.sstatic.net/Sites/ru/img/sprites.svg?v=f508971f422f);
  background-position: 0 0; background-size: 400px;
  transform: rotateX(5deg) rotateY(180deg);
}
.stack__active {animation: stack 4s linear infinite;}
@keyframes stack {
  0% {transform: rotateX(5deg) rotateY(-180deg);}
  100% {transform: rotateX(5deg) rotateY(180deg);}
}
<div class="container">
  <div class="transform">
    <div id="cube">
      <div class="cube front"></div>
      <div class="cube back"></div>
      <div class="cube top"></div>
      <div class="cube left"></div>
      <div class="cube right"></div>
      <div class="cube bottom"></div>
      <div class="stack"></div>
    </div>
  </div>
</div>

→ Ссылка