Daj Się Poznać #8 stylowanie aplikacji


W poprzednich częściach tworzyliśmy quiz Mistrz Makro, pozwalający na sprawdzenie rozbieżności w diecie IIFYM. Zbudowaliśmy całą działającą aplikację w AngularJS, a w poprzednim artykule zrefaktoryzowaliśmy kod przy użyciu standardu JavaScript ES6. Tym razem nadamy wygląd naszej animacji korzystając z preprocesora CSS, czyli LESS. Stworzymy kilka animacji, które upiększą i poprawią interfejs aplikacji. Zaczynajmy!

Jeśli pobrałeś już moje repozytorium z Githuba, co opisałem w poprzednim poście to możesz teraz przeskoczyć do kolejnego commita, który pokaże Ci kod z tego posta:
$ git checkout bbfcb167b0b5841b52e703e6c3e7484079452e4a

# Plik HTML komponentu

Podjąłem decyzję, że jednak nie będę korzystał z bootstrapa, ponieważ nie będzie w ogóle przydatny w tym co planuję zrobić. Założeniem jest responsywny kontener, wycentrowany na ekranie, przypominający kartę z animacją obracania się. Po jednej strony karty znajdą się inputy do wprowadzenia wartości, a po drugiej wynik po sprawdzeniu danych.

mainFile.html, czyli kod naszego komponentu:

 
  <div class="container" ng-show="c.inProgress">
  <div class="flip" ng-show="!c.quizEnd"> 
    <div class="card" ng-class="{'flipped':isFlipped}">
      <div class="face front"> 
        <h2></h2>
        <img ng-src="/assets/">
        <p>Kcal:</p><input type="number" ng-model="c.macro1">
        <p>Białko:</p><input type="number" ng-model="c.macro2">
        <p>Węglowodany:</p><input type="number" ng-model="c.macro3">
        <p>Tłuszcz:</p><input type="number" ng-model="c.macro4">
        <button class="nextBtn" ng-click="c.check(); isFlipped=!isFlipped" ng-show="c.answerMode">Submit</button>
      </div> 
      <div class="face back"> 
        <h2></h2>
        <img ng-src="/assets/">
        <p>Kcal: kcal to </p>
        <p>Białko: g białka to </p>
        <p>Węglowodany: g węglowodanów to </p>
        <p>Tłuszcz: g tłuszczu to </p>
        <button class="text-center nextBtn" ng-click="isFlipped=!isFlipped; c.nextQuestion()">Next</button>
      </div> 
    </div> 
  </div>
  <div class="container" ng-class="{ 'start__outer' : c.quizEnd }">
    <div ng-show="c.quizEnd" class="midButton">
      <h1>Mistrz Makro</h1>
      <button ng-click="c.reset()">Play again</button>
    </div>
  </div>
</div>

<div class="container" ng-class="{ 'start__outer' : !c.inProgress }">
  <div class="midButton" ng-show="!c.inProgress">
    <h1>Mistrz Makro</h1>
    <button ng-click="c.start()">Start</button>
  </div>
</div>

Pojawił się div flip, który będzie naszą kartą. Klasy front i back odpowiadają za awers i rewers karty, stąd w jednym znajdują się inputy, a w drugim wartości wynikowe.

Na przyciskach Submit i Next mamy w ng-click isFlipped=!isFlipped, zmieniające zmienną odpowiadającą za obrót karty w divie card, który posiada fragment kodu ng-class="{'flipped':isFlipped}". Oznacza to, że div otrzyma klasę flipped, jeśli zmienna będzie miała wartość true.

Na ekranie "start" i "play again" dodajemy klasę start__outer kodem ng-class="{ 'start__outer' : c.quizEnd }", ponieważ stworzone cssy mogą mieć problem z ng-show.

# Style LESS

 
.flip {
  -webkit-perspective: 800;
  height: 580px;
  width: 357px;
  position: relative;
  margin: 20px auto;
  h2{
    text-align: center;
  }
  img, p{
    padding-left: 30px;
  }
  input{
    margin-left: 30px;
  }
  button{
    display: block;
    margin: 15px auto;
  }
  .nextBtn{
    position: absolute;
    top:505px;
    left:30px;
  }
}

Na początek stworzymy sobie kartę określając jej wymiary. Fragment margin: 20px auto; odpowiada za centrowanie karty na samym środku ekranu z zachowaniem responsywności. Nadajemy pozycję relatywną, ponieważ będziemy pozycjonować przyciski .nextBtn absolutnie. Odsuwamy od lewej krawędzi paddingami i marginesami nasze napisy i inputy. Nadajemy przyciskowi wartość display:block, zeby przesunąć go do nowej lini i także centrujemy go wewnątrz karty.

 
.flip .card.flipped {
  -webkit-transform: rotatex(-180deg);
}

.flip .card {
  width: 100%;
  height: 100%;
  -webkit-transform-style: preserve-3d;
  -webkit-transition: 0.5s;
}

Tworzymy klasy potrzebne do animacji obrotu.

 
.flip .card .face {
  width: 100%;
  height: 100%;
  position: absolute;
  -webkit-backface-visibility: hidden;
  z-index: 2;
  border: 0px;
  border-radius: 25px;
}

Określamy za pomocą border-radius, żeby nasza karta miała zaokrąglone rogi. Za pomocą backface-visibity ustawiamy, żeby druga strona karty nie była widoczna po odwróceniu.

 
.flip .card .front {
  position: absolute;
  z-index: 1;
  background: #708090;
  color: white;
  p{
    margin-top: 10px;
    margin-bottom: 10px;
  }
  input{
    color: black;
  }
}

.flip .card .back {
  -webkit-transform: rotatex(-180deg);
  background: #36454F;
  color: white;
}  

W klasie front ustalamy kolor awersu karty, odstępy między paddingami oraz kolor tekstu wewnątrz inputu jako czarny, ponieważ cały tekst w aplikacji jest koloru białego. W klasie back również ustalamy kolor i sposób obrotu.

 
button{
  background-color: #536878;
  border-radius: 10px;
  color: white;
  border: 0;
  padding: 10px;
  width: 297px;
} 

Określamy rozmiar, kształt, kolor tła i czcionki wszystkich przycisków

Tak wygląda awers naszej karty:

A Tak będzie wyglądal rewers:

# Animacja infinite scrolling background

Na ekranie tytułowym, oraz "play again" wstawimy tło, które będzie się powtarzać i przewijać w nieskończoność z dołu go góry.

Grafikę stworzyłem w Inkscape i wyeksportowałem jako PNG:

 
.start__outer{
  width: 297px;
  min-height: 620px;
  height: 100vh;
  margin: 0 auto;
  background-image: url('http://localhost:3000/assets/b.png');  
  -webkit-animation:100s scroll infinite linear;
  -moz-animation:100s scroll infinite linear;
  -o-animation:100s scroll infinite linear;
  -ms-animation:100s scroll infinite linear;
  animation:100s scroll infinite linear;
}

Klasa start__outer jest dodawana zależnie od aktuanych stanów, co można zaobserwować w kodzie HTML powyżej. Ustawiliśmy tam wysokość 100vh, czyli 100% wysokości danego urządzenia, z zastrzeżeniem, że najmniej może to być 620px. Ustawiliśmy zdjęcie na tło, oraz nie wyłączyliśmy background-repeat. Zastosowaliśmy animację scroll, którą określiliśmy poniżej.

 
@-webkit-keyframes scroll{
  100%{
    background-position:0px -3000px;
  }
}

@-moz-keyframes scroll{
  100%{
    background-position:0px -3000px;
  }
}

@-o-keyframes scroll{
  100%{
    background-position:0px -3000px;
  }
}

@-ms-keyframes scroll{
  100%{
    background-position:0px -3000px;
  }
}

@keyframes scroll{
  100%{
    background-position:0px -3000px;
  }
}

Tak będzie wyglądać ekran startowy, tylko z tłem poruszającym się od dołu do góry:

Published: May 21 2017

blog comments powered by Disqus