11 Wrz 2019

Animacja 3d w css

Animacja 3d w css możliwa już od wersji IE10, za pomocą przychodzi nam parametr perspective.
Nasza animacja będzie polegała na obracaniu sześcianu. Jak wiemy sześcian to sześć ścian więc zaczniemy od nich.

<div class="scene">
  <div class="cube">
    <div class="cube__wall cube__front">front</div>
    <div class="cube__wall cube__back">back</div>
    <div class="cube__wall cube__right">right</div>
    <div class="cube__wall cube__left">left</div>
    <div class="cube__wall cube__top">top</div>
    <div class="cube__wall cube__bottom">bottom</div>
  </div>
</div>

Jak widać nic szczególnego, scene – która zawiera div [cube] wraz z sześcioma ścianami. Każda ze ścian posiada napis tak aby można było zauważysz rotację tej kostki.
Teraz same „mięsko” a mianowicie css. Zaczynamy od podstaw zbudowanie podstaw, body na 100% wysokości do tego dodam animację backgroundu – tutaj wykorzystałem z [ generatora gradientów ]

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

html {
  height: 100%;
}

body {
  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100%;
  background-color: #f0f0f0;
  background-image: linear-gradient(to right bottom, #051937, #004a7b, #0081a0, #00b993, #12eb54);
  background-size: 200% 200%;
  animation: animationGradient 5s ease infinite;
}

@keyframes animationGradient {
  0% {
    background-position: 10% 0%
  }

  50% {
    background-position: 91% 100%
  }

  100% {
    background-position: 10% 0%
  }
}

Teraz najważniejszy element, css odpowiedzialny za wygląd sześcianu.

.scene {
  width: 200px;
  height: 200px;
  margin: 100px;
  perspective: 400px;
}

.cube {
  width: 200px;
  height: 200px;
  position: relative;
  transform-style: preserve-3d;
  transform: translateZ(-100px);
}

.cube__wall {
  position: absolute;
  width: 200px;
  height: 200px;
  border: 3px solid #000;
  display: flex;
  justify-content: center;
  align-items: center;
  font-weight: bold;
  font-size: 2rem;
  text-transform: uppercase;
  color: #fff;
}

.cube__front {
  background: rgba(255, 0, 0, 0.6);
  transform: rotateY(0deg) translateZ(100px);
}

.cube__back {
  background: rgba(0, 38, 255, 0.6);
  transform: rotateY(180deg) translateZ(100px);
}

.cube__right {
  background: rgba(0, 255, 33, 0.6);
  transform: rotateY(90deg) translateZ(100px);
}

.cube__left {
  background: rgba(105, 101, 37, 0.6);
  transform: rotateY(-90deg) translateZ(100px);
}

.cube__top {
  background: rgba(255, 0, 233, 0.6);
  transform: rotateX(90deg) translateZ(100px);
}

.cube__bottom {
  background: rgba(251, 255, 0, 0.6);
  transform: rotateX(-90deg) translateZ(100px);
}

W klasie scene musimy ustawić perspective: 400px; Parametr ten daje nam głębie 3d. Warto nim się pobawić i zobaczyć jak zmienia się perspektywa w zależności ile ustawimy px.
Klasa cube składa się z transform-style: preserve-3d; Ta właściwość ustala, że elementy potomne – dzieci znajdują się w tej samej perspektywie co element nadrzędny.

Klasa cube__wall ustawia nam wszystkie ściany jako absolute, inaczej nie moglibyśmy zmieniać położenia za pomocą
rotateY, rotateX oraz translateZ, klasa ta posiada również pozycjonowanie napisów [front, bottom, left, right, back].

Reszta klas odpowiada za pozycję ‚ścian’. Każda ze ścian posiada kolor z transparentnością ustawioną na 0.6.

Do pełni szczęścia brakuje nam animacji naszego sześcianu 😉
Tutaj do klasy cube dodamy animation: rotationCube 10s infinite ease-in-out
Animacja nazywa się rotationCube trwającą 10s, infinitie czyli w nieskończoność powtarzana, a ease-in-out jest rodzajem animacji.

.cube {
  width: 200px;
  height: 200px;
  position: relative;
  transform-style: preserve-3d;
  transform: translateZ(-100px);
  animation: rotationCube 10s infinite ease-in-out;
}

@keyframes rotationCube {
  0% {
    transform: translateZ(-100px) rotateX(0deg) rotateY(0deg);
  }

  50% {
    transform: translateZ(50px) rotateX(-360deg) rotateY(-360deg);
  }

  100% {
    transform: translateZ(-100px) rotateX(0deg) rotateY(360deg);
  }
}

Poniżej cały działający przykład. polecam pobawić się ustawieniami. Np. do klasy cube__wall dodać box-shadow box-shadow: 0 0 0 20px rgba(255, 255, 255, 0.5) bardzo ciekawy efekt 😉