CSS3 - Konflikt punktu zero oraz punktu środka perspektywy

Jak wiemy jednym ze sposobów, aby utworzyć dla interesującego nas elementu HTML perspektywę jest skorzystanie z funkcji perspective() właściwości transform.

Spróbujmy utworzyć w ten sposób perspektywę dla przykładowego elementu HTML oraz sprawmy, aby element HTML stał się animowanym elementem 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(500px) rotate(0) rotateX(0); }
  100% { transform:perspective(500px) rotate(360deg) rotateX(360deg); }
}

Rezultat:

DIV

Korzystając z wiedzy, jaką zdobyliśmy podczas poznawania poprzednich części tego kursu CSS utworzyliśmy animowany element HTML w przestrzeni 3D wykorzystując do tego celu regułę @keyframes oraz właściwość animation. Perspektywa dla naszego przykładowego elementu div jest tworzona podczas wykonywania się przykładowej animacji na wspomnianym elemencie div, dzięki funkcji perspective(500px) oraz właściwości transform o czym była już mowa w poprzednich częściach tego kursu. Nasza przykładowa animacja obraca danym elementem HTML równocześnie wokół jego punktu zero od wartości 0 do wartości 360deg (dzięki funkcji rotate()) oraz wokół jego poziomu, czyli osi X, od wartości 0 do wartości 360deg (dzięki funkcji rotateX()).

Zobaczmy co się stanie z wyglądem naszego przykładowego elementu div oraz jego animacji, gdy do wspomnianego elementu div dodamy właściwość transform-origin wraz z wartością 0 0.

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;
  transform-origin:0 0;
}

@keyframes naszaAnimacja
{
  0% { transform:perspective(500px) rotate(0) rotateX(0); }
  100% { transform:perspective(500px) rotate(360deg) rotateX(360deg); }
}

Rezultat:

DIV

Po dodaniu właściwości transform-origin:0 0; do naszego przykładowego elementu HTML wygląd jego animacji zmienił się. Wygląd nowo powstałej animacji nie jest sam w sobie błędny (element HTML wygląda jakby tańczył wokół własnego lewego górnego rogu), lecz jak już zdążyliśmy się przyzwyczaić właściwość transform-origin oddziałuje na różne ważne cechy dotyczące tego jak ostatecznie będzie wyglądał interesujący nas element HTML po przekształceniu go za pomocą różnych funkcji właściwości transform.

Gdy dodajemy do interesującego nas elementu HTML właściwość transform-origin wraz z dwoma wartościami, wspomniane wartości kontrolują pozycję punktu zero danego elementu HTML, czyli miejsce przecięcia się pionowej osi Y oraz poziomej osi X. Jak wiemy wspomniana pozycja punktu zero danego elementu HTML wpływa na ostateczny wygląd elementu HTML, gdy przekształcimy wspomniany element HTML za pomocą niektórych funkcji właściwości transform, które służą do przekształcenia elementu HTML w przestrzeni 2D.

Ponadto gdy do elementu HTML dodamy właściwość transform wraz z funkcją perspective() punkt środka perspektywy danego elementu HTML (na podstawie którego jest tworzona perspektywa dla danego elementu HTML) jest odsuwany o wartość, którą podaliśmy wraz z funkcją perspective() od miejsca przecięcia się pionowej osi Y oraz poziomej osi X, których położenie jest uzależnione od dwóch pierwszych wartości właściwości transform-origin. Jak wiemy wspomniana pozycja punktu środka perspektywy danego elementu HTML wpływa na ostateczny wygląd elementu HTML, gdy przekształcimy wspomniany element HTML za pomocą niektórych funkcji właściwości transform, które służą do przekształcenia elementu HTML w przestrzeni 3D.

W naszym przykładzie wszystkie wyżej wymienione zasady zostały spełnione, ponieważ animacja naszaAnimacja korzysta z trzech funkcji właściwości transform, które pasują do zasad, które zostały wymienione powyżej. Funkcja perspective() tworzy perspektywę dla danego elementu HTML. Funkcja rotate() przekształca dany element HTML na podstawie miejsca punktu zero wspomnianego elementu HTML. Funkcja rotateX() przekształca dany element HTML na podstawie miejsca punktu środka perspektywy wspomnianego elementu HTML. Dlatego gdy do naszego przykładowego elementu HTML dodaliśmy właściwość transform-origin:0 0; zmieniliśmy położenie pionowej osi Y oraz poziomej osi X, dzięki czemu miejsce punktu zero oraz miejsce punktu środka perspektywy zostały jednocześnie zmienione.

W tym momencie tworzy się pewien konflikt pomiędzy sposobem manipulacji punktem zero danego elementu HTML oraz sposobem manipulacji punktem środka perspektywy danego elementu HTML. Co prawda wspomniany konflikt nie tworzy żadnych błędów, lecz co w wypadku gdybyśmy chcieli osobno manipulować wspomnianymi punktami danego elementu HTML?

Wyjście z tej sytuacji jest dosyć proste.

Musimy sprawić, aby tylko jeden element HTML był odpowiedzialny za utworzenie perspektywy dla wszystkich swoich elementów dzieci.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Darmowy Kurs CSS</title>

    <style>
      #perspektywa {
        perspective:500px;
        perspective-origin:100% 100%;
        height:300px;
        background-color:rgba(255,0,0,0.8);
      }

      #dziecko {
        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;
        transform-origin:0 0;
      }

      @keyframes naszaAnimacja
      {
        0% { transform:rotate(0) rotateX(0); }
        100% { transform:rotate(360deg) rotateX(360deg); }
      }
    </style>
  </head>

  <body>

    <div id="perspektywa">
      <div id="dziecko">DIV</div>
    </div>

  </body>
</html>

Rezultat:

DIV

W naszym przykładzie umieściliśmy jeden element div w drugim elemencie div. Dla obu wspomnianych elementów div określiliśmy różny atrybut id. Element #perspektywa jest elementem rodzicem dla elementu #dziecko. Do elementu #perspektywa dodaliśmy właściwość perspective wraz z wartością 500px, dzięki czemu element #dziecko znalazł się w zasięgu perspektywy o wartości 500px tworzonej przez jego element rodzic, czyli element #perspektywa. W tym momencie manipulacja punktem środka perspektywy tworzonej przez element #perspektywa jest możliwa za pomocą dwóch wartości właściwości perspective-origin, którą należy dodać do elementu HTML, do którego została dodana właściwość perspective, czyli w naszym przykładzie do elementu #perspektywa. Natomiast manipulacja punktem zero elementu #dziecko jest możliwa za pomocą dwóch wartości właściwości transform-origin. Ponadto w regule @keyframes o nazwie naszaAnimacja nie musimy już podawać funkcji perspective() dla właściwości transform, ponieważ w naszym przykładzie, gdy dodamy w ten sposób utworzoną animację do elementu #dziecko, element #dziecko znajduje się już w zasięgu perspektywy tworzonej przez jego element #perspektywa, dlatego przeglądarka internetowa poradzi sobie z funkcją rotateX(), która pojawiła się w zapisie naszej reguły @keyframes o nazwie naszaAnimacja, oraz która służy do przekształcenia elementu HTML w przestrzeni 3D.

Podsumowując możemy dostrzec, iż od tej pory mamy osobny wpływ na to gdzie zostanie umieszczony punkt zero interesującego nas elementu HTML oraz punkt środka interesującej nas perspektywy, dzięki czemu osobno możemy kontrolować cechy wyglądu danego elementu HTML, które są uzależnione od przekształcenia danego elementu HTML za pomocą funkcji 2D właściwości transform, oraz które są uzależnione od przekształcenia danego elementu HTML za pomocą funkcji 3D właściwości transform.

Jeżeli chcielibyśmy zachować wszystkie opisane wyżej zależności, a dodatkowo chcielibyśmy aby element #perspektywa znalazł się w zasięgu swojej własnej perspektywy (dzięki właściwości transform:perspective(500px);), którą dzieliłby ze swoimi elementami dziećmi (dzięki właściwości transform-style:preserve-3d;), musimy zrezygnować z właściwości perspective (na rzecz wspomnianej funkcji perspective() właściwości transform) oraz właściwości perspective-origin (na rzecz właściwości transform-origin).

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Darmowy Kurs CSS</title>

    <style>
      #perspektywa {
        transform:perspective(500px);
        transform-origin:100% 100%;
        transform-style:preserve-3d;
        height:300px;
        background-color:rgba(255,0,0,0.8);
      }

      #dziecko {
        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;
        transform-origin:0 0;
      }

      @keyframes naszaAnimacja
      {
        0% { transform:rotate(0) rotateX(0); }
        100% { transform:rotate(360deg) rotateX(360deg); }
      }
    </style>
  </head>

  <body>

    <div id="perspektywa">
      <div id="dziecko">DIV</div>
    </div>

  </body>
</html>

Rezultat:

DIV

W następnej części kursu CSS przyjrzymy się pozycji relatywnej, absolutnej oraz ustalonej w kontekście przekształceń elementu HTML w przestrzeni.