CSS3 - Tworzenie animacji w przestrzeni 3D

Podczas zapoznawania się z kolejnymi zagadnieniami dotyczącymi przekształcenia elementu HTML w przestrzeni 2D oraz przestrzeni 3D mogliśmy zobaczyć różne animacje, które zostały wykonane wyłącznie za pomocą języka CSS. W tej części kursu CSS poznamy kilka istotnych informacji, które przydadzą się nam gdy zechcemy utworzyć animowany element HTML w przestrzeni.

Na początek utworzymy przykładowy element HTML.

div {
  width:150px;
  height:150px;
  margin:0 auto;
  background-color:#000;
  color:#FFF;
  text-align:center;
  line-height:50px;
  font-size:26px;
}

Rezultat:

DIV

Jak wiemy, aby utworzyć animację w języku CSS najpierw należy wykorzystać do tego celu regułę @keyframes oraz selektory czasu animacji. Nasza pierwsza przykładowa animacja będzie obracać elementem HTML wokół jego pionu, a więc wspomniana animacja będzie wykonywała się w przestrzeni 3D, a więc interesujący nas element HTML musi znaleźć się w zasięgu perspektywy.

Tworzymy przykładową regułę @keyframes o nazwie naszaAnimacja, która ma obracać elementem HTML wokół jego pionu o wartość 360 stopni.

@keyframes naszaAnimacja
{
  0% { transform:rotateY(0); }
  100% { transform:rotateY(360deg); }
}

W ten sposób utworzoną regułę @keyframes o nazwie naszaAnimacja, czyli animację o nazwie naszaAnimacja dodajemy do naszego przykładowego elementu div za pomocą właściwości animation.

div {
  width:150px;
  height:150px;
  margin:0 auto;
  background-color:#000;
  color:#FFF;
  text-align:center;
  line-height:50px;
  font-size:26px;
  animation:naszaAnimacja 4s linear infinite;
}

@keyframes naszaAnimacja
{
  0% { transform:rotateY(0); }
  100% { transform:rotateY(360deg); }
}

Rezultat:

DIV

Reguła @keyframes o nazwie naszaAnimacja, gdy zostanie dodana do elementu HTML, obraca danym elementem HTML wokół jego pionu rozpoczynając wspomniany obrót od wartości 0, a kończąc na wartości 360deg (dzięki właściwości transform oraz funkcji rotateY()).

Zapis animation:naszaAnimacja 4s linear infinite; dodaje do danego elementu HTML animację o nazwie naszaAnimacja, która została utworzona za pomocą reguły @keyframes, sprawia że dana animacja trwa cztery sekundy (4s), sprawia że dana animacja ma stałe tempo (linear), sprawia że dana animacja powtarza się od początku do końca w nieskończoność (infinite).

Rezultat, jaki ujrzeliśmy nie jest rezultatem, który oczekiwaliśmy, ponieważ nasz przykładowy elementem HTML nie obraca się w przestrzeni 3D tylko w przestrzeni 2D przez co cały efekt wygląda jakby dany element był skalowany względem poziomu.

Jak wiemy, aby przeglądarka internetowa mogła prawidłowo wykonać przekształcenie za pomocą funkcji 3D na interesującym nas elemencie HTML (w naszym przykładzie za pomocą funkcji rotateY() na elemencie div), element ten musi znaleźć się w zasięgu perspektywy.

Dodajemy do naszego przykładowego elementu div perspektywę za pomocą właściwości transform oraz funkcji perspective().

div {
  width:150px;
  height:150px;
  margin:0 auto;
  background-color:#000;
  color:#FFF;
  text-align:center;
  line-height:50px;
  font-size:26px;
  transform:perspective(300px);
  animation:naszaAnimacja 4s linear infinite;
}

@keyframes naszaAnimacja
{
  0% { transform:rotateY(0); }
  100% { transform:rotateY(360deg); }
}

Rezultat:

DIV

Rezultat nie zmienił się.

Dlaczego?

Ponieważ zarówno w regule @keyframes oraz w regule utworzonej za pomocą selektora div wykorzystaliśmy właściwość transform oznacza to, że gdy dodamy regułę @keyframes o nazwie naszaAnimacja do naszego przykładowego elementu div za pomocą właściwości animation, właściwość transform znajdująca się w selektorach czasu animacji wspomnianej reguły @keyframes nadpisze ewentualną właściwość transform, która znajduje się w regule utworzonej za pomocą selektora div, a więc w rezultacie właściwość transform:perspective(300px); jest już na starcie animacji nadpisana przez właściwość transform:rotateY(0); znajdującą się w selektorze 0% reguły @keyframes, dlatego nasz przykładowy element div ciągle nie znajduje się w zasięgu żadnej perspektywy.

Wyjście z opisanej sytuacji jest bardzo proste. Wystarczy wykorzystać funkcję perspective(300px) w naszej przykładowej regule @keyframes o nazwie naszaAnimacja wraz z właściwością transform oraz funkcją rotateY().

div {
  width:150px;
  height:150px;
  margin:0 auto;
  background-color:#000;
  color:#FFF;
  text-align:center;
  line-height:50px;
  font-size:26px;
  animation:naszaAnimacja 4s linear infinite;
}

@keyframes naszaAnimacja
{
  0% { transform:perspective(300px) rotateY(0); }
  100% { transform:rotateY(360deg) perspective(300px); }
}

Rezultat:

DIV

Tym razem nie zobaczyliśmy żadnej animacji.

Dlaczego?

Ponieważ w naszym zapisie popełniliśmy drobny błąd. Gdy tworzymy animację wykorzystując do tego celu regułę @keyframes, w której chcemy wykorzystać właściwość transform z kilkoma funkcjami naraz w kilku różnych selektorach czasu animacji reguły @keyframes (w naszym przykładzie jest to selektor 0% oraz selektor 100%) musimy zachować taką samą kolejność podawania kolejnych funkcji właściwości transform w kolejnych selektorach animacji danej reguły @keyframes.

W naszym zapisie widzimy 0% { transform:perspective(300px) rotateY(0); } oraz 100% { transform:rotateY(360deg) perspective(300px); }, dlatego drugi zapis musimy zmienić na 100% { transform:perspective(300px) rotateY(360deg); }.

div {
  width:150px;
  height:150px;
  margin:0 auto;
  background-color:#000;
  color:#FFF;
  text-align:center;
  line-height:50px;
  font-size:26px;
  animation:naszaAnimacja 4s linear infinite;
}

@keyframes naszaAnimacja
{
  0% { transform:perspective(300px) rotateY(0); }
  100% { transform:perspective(300px) rotateY(360deg); }
}

Rezultat:

DIV

Od tej pory nasz przykładowy element div znajduje się w perspektywie o wartości 300px przez cały czas trwania naszej przykładowej animacji naszaAnimacja, dzięki czemu w rezultacie widzimy jak nasz przykładowy element div obraca się wokół własnego pionu w przestrzeni 3D od wartości 0 do wartości 360deg w nieskończoność.

Czasami, gdy wykonujemy jakąś animację na elemencie HTML chcemy, aby tylna strona elementu HTML została ukryta. Tylną stronę elementu HTML możemy zobaczyć, np. w momencie gdy dany element HTML jest obrócony względem swojego pionu o wartość od 90deg do wartości 270deg. Nasza przykładowa animacja obraca elementem HTML od wartości 0 do wartości 360deg względem pionu, a więc przedział wartości od wartości 90deg do 270deg mieści się we wspomnianym przedziale od wartości 0 do wartości 360deg.

Aby ukryć tylną stronę elementu HTML podczas przekształcania go w przestrzeni 3D za pomocą funkcji właściwości transform należy wykorzystać do tego celu właściwość backface-visibility wraz z wartością hidden.

div {
  width:150px;
  height:150px;
  margin:0 auto;
  background-color:#000;
  color:#FFF;
  text-align:center;
  line-height:50px;
  font-size:26px;
  animation:naszaAnimacja 4s linear infinite;
  backface-visibility:hidden;
}

@keyframes naszaAnimacja
{
  0% { transform:perspective(300px) rotateY(0); }
  100% { transform:perspective(300px) rotateY(360deg); }
}

Rezultat:

DIV

Gdy poznawaliśmy funkcje właściwości transform, które służą do przekształcenia elementu HTML w przestrzeni 2D dowiedzieliśmy się, że możemy podać kilka funkcji jednocześnie wraz w właściwością transform. Taka sama sytuacja dotyczy funkcji właściwości transform, które służą do przekształcenia elementu HTML w przestrzeni 3D. Ponadto to w jakiej kolejności zostaną podane przez nas kolejne funkcje właściwości transform ma wpływ na ostateczny wygląd elementu HTML.

div {
  width:150px;
  height:150px;
  margin:0 auto;
  background-color:#000;
  color:#FFF;
  text-align:center;
  line-height:50px;
  font-size:26px;
  animation:naszaAnimacja 4s linear infinite;
}

@keyframes naszaAnimacja
{
  0% { transform:perspective(300px) rotateY(0) translateX(0); }
  100% { transform:perspective(300px) rotateY(360deg) translateX(150px); }
}

Rezultat:

DIV

Zobaczmy teraz jak będzie wyglądała nasza przykładowa animacja, gdy zmienimy kolejność funkcji właściwości transform, czyli gdy podamy funkcję translateX() przed funkcją rotateY().

div {
  width:150px;
  height:150px;
  margin:0 auto;
  background-color:#000;
  color:#FFF;
  text-align:center;
  line-height:50px;
  font-size:26px;
  animation:naszaAnimacja 4s linear infinite;
}

@keyframes naszaAnimacja
{
  0% { transform:perspective(300px) translateX(0) rotateY(0); }
  100% { transform:perspective(300px) translateX(150px) rotateY(360deg); }
}

Rezultat:

DIV

Ponadto możemy zauważyć, że nic nie stoi nam na przeszkodzie, aby jednocześnie przekształcić interesujący nas element HTML zarówno za pomocą funkcji 2D (w naszym przykładzie jest to funkcja translateX()), jak i funkcji 3D (w naszym przykładzie jest to funkcja rotateY()).

Podczas poznawania funkcji 2D dowiedzieliśmy się, że za pomocą funkcji rotate() możemy zmienić kierunek, w który będzie przekształcany dany element HTML za pomocą kolejnych funkcji translateX() lub translateY(). Podobnie jest w kontekście przekształceń w przestrzeni 3D, ponieważ za pomocą funkcji rotateX() lub funkcji rotateY() możemy kontrolować kierunek przekształcenia, w którym to kierunku interesujący nas element HTML zostanie przekształcony za pomocą funkcji translateZ() właściwości transform.

div {
  width:150px;
  height:150px;
  margin:0 auto;
  background-color:#000;
  color:#FFF;
  text-align:center;
  line-height:50px;
  font-size:26px;
  animation:naszaAnimacja 4s linear infinite;
}

@keyframes naszaAnimacja
{
  0% { transform:perspective(300px) translateZ(0); }
  100% { transform:perspective(300px) translateZ(150px); }
}

Rezultat:

DIV

Jak widzimy domyślnie element HTML przekształcany za pomocą funkcji translateZ() właściwości transform jest przekształcany w kierunku prostopadłym do naszego wzroku czy też ekranu naszego urządzenia.

Zobaczmy co się stanie z naszą animacją oraz elementem HTML, gdy przed funkcją translateZ() umieścimy funkcję rotateY().

div {
  width:150px;
  height:150px;
  margin:0 auto;
  background-color:#000;
  color:#FFF;
  text-align:center;
  line-height:50px;
  font-size:26px;
  animation:naszaAnimacja 4s linear infinite;
}

@keyframes naszaAnimacja
{
  0% { transform:perspective(300px) rotateY(0) translateZ(0); }
  100% { transform:perspective(300px) rotateY(45deg) translateZ(150px); }
}

Rezultat:

DIV

Jak możemy dostrzec na naszej przykładowej animacji, kierunek przekształcenia danego elementu HTML za pomocą funkcji translateZ() właściwości transform uległ nieco zmianie. Co prawda element HTML jest przesuwany bardziej do naszego wzroku, lecz tym razem nie prostopadle, lecz nieco bardziej w naszą prawą stronę. Zmianę tę umożliwia funkcja rotateY(), która została umieszczona przed funkcją translateZ().

W następnej części kursu CSS poznamy czym jest sfera i jak może wpłynąć ona na wygląd elementu HTML w kontekście przekształceń w przestrzeni 3D.