Анимация граней на изометрическом кубе 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 шт):
Обновите порядок преобразования, чтобы сначала подвинуть (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.
А-ля презентация 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>