Carousel card
W tym artykule przedstawię krok po kroku jak samemu zrobić stosunkowo prostą, responsywną, przewijaną kartę, przy wykorzystaniu Bootstrapa, CSS'a i odrobiny jQuery.Pierwszym krokiem będzie pobranie i rozpakowanie paczki MDBootsrap. Gdy już to zrobicie, waszym oczom ukaże się wiele plików, ale nas interesować będą tylko trzy z nich:
index.html
css/style.css
js/script.js
(ten plik musicie stworzyć sami)
Następnie w pliku index.html
usuwamy wszystko, co znajduje się pomiędzy komentarzami
Start your project here - tam będzie mieścił się nasz kod.
Dla lepszego przedstawienia zamknijmy naszą kartę w containerze, pozwoli to nam określić jej wielkość położenie itp. W tym celu wpiszmy do HTML następujący kod:
<!-- Start your project here-->
<div class="container mt-5 col-12 col-md-8 p-0">
</div>
<!-- Start your project here-->
Do naszego containera dodaliśmy kilka klas w celu zapewnienia responsywności:
container
określa, że jest to containercol-12
na małych ekranach zajmuje całą szerokośćcol-md-8
na ekranach większych niż 768 pixeli zajmuje tylko 8/12 szerokości
Następnie stwórzmy już naszą właściwą kartę i nadajmy jej klasy, które pomogą nam zdefiniować jej właściwości bez potrzeby pisania ich w CSS.
<!-- Start your project here-->
<div class="container mt-5 col-12 col-md-8 p-0">
<div class="card carousel-card d-flex m-5 flex-column flex-lg-row">
</div>
</div>
<!-- Start your project here-->
card
nasz div przybierze standarowy wygląd bootstrapowej kartycarousel-card
ta klasa przyda nam się później przy CSSd-flex
określimy tym właściwość display i ustalimy ją na flex, co pozwoli nam na łatwiejsze ustawienie elementów w naszej karciem-5
ustala odpowiednie marginesy aby nasza karta zachowywała odstęp od innych elementów na stronieflex-column
dzięki tej klasie obiekty w środku naszego diva wyświetlane będą jeden pod drugimflex-lg-row
ta klasa nada naszej karcie responsywności i przy większych ekranach (minimum 992px) obiekty w divie będą wyświetane jeden obok drugiego
Naszą kartę podzielimy na 2 części, lewą zawierającą obrazek i prawą zawierającą tekst. W tym celu utworzymy sobie 2 kolejne divy i nadamy im odpowiednie klasy.
Lewa strona
Zacznijmy od strony lewej, która będzie mniej skomplikowana, bo jedyne, co musimy zrobić, to wejść na dokumentację i przekleić karuzelę zdjęć.
Link do dokumentacjiKopiujemy pierwszy przykład i wklejamy go do naszej karty.
<!-- Start your project here-->
<div class="container mt-5 col-12 col-md-8 p-0">
<div class="card carousel-card d-flex m-5 flex-column flex-lg-row">
<div id="carouselExampleSlidesOnly" class="carousel slide carousel-card-image" data-ride="carousel" data-interval="false">
<div class="carousel-inner">
<div class="carousel-item active">
<img class="d-block w-100" src="https://i.ibb.co/wsgXZ8N/game-cartridges-1373100-1.jpg">
</div>
<div class="carousel-item">
<img class="d-block w-100" src="https://i.ibb.co/vDHfqwq/technology-computer-lines-board-50711.jpg">
</div>
<div class="carousel-item">
<img class="d-block w-100" src="https://i.ibb.co/FBwHfry/person-playing-chess-1040157.jpg">
</div>
</div>
</div>
</div>
</div>
<!-- Start your project here-->
Jak już pewnie zdążyliście zauważyć - dodałem do naszej karuzeli klasę
.carousel-card-image
. Pozwoli nam ona na późniejsze dostosowanie naszej karuzeli w
CSS.
Dodałem również atrybut data-interval="false"
, który sprawi, że zdjęcia nie będą
przewijały się samoczynnie. Bez obaw - ta funkcja będzie dostępna, ale zrobimy ją po
swojemu.
Prawa strona
Stwórzmy więc diva, który będzie zawierał w sobie całą prawą stronę, tj. przyciski, którymi będziemy mogli kontrolować naszą karuzelę, loader, który będzie przełączał nam automatycznie karty, a także sam content w postaci tekstu oraz odnośnika. Nadajmy mu również klasę, dzięki której później bedziemy mogli się do niego odwołać i umieśćmy go poniżej wklejonej przez nas niedawno karuzeli.
<div class="carousel-right flex-column d-flex">
</div>
Teraz podzielmy sobie naszego nowo stworzonego diva na dwie części. W pierwszej będą mieścić się narzędzia kontrolne, czyli przyciski i loader, a w drugiej umieścimy tekst.
<div class="carousel-right flex-column d-flex">
<div class='d-flex flex-row justify-content-between p-3'>
<div class='carousel-contents card-body carousel slide pt-0' data-interval="false" data-ride="carousel">
<div class="carousel-inner h-100">
<div class="carousel-item h-100 active">
</div>
<div class="carousel-item h-100">
</div>
<div class="carousel-item h-100">
</div>
</div>
</div>
Do pierwszego diva dodamy 3 klasy:
d-flex
określimy tym właściwość display i ustalimy ją na flex, co pozwoli nam na łatwiejsze ustawienie elementów w naszej karcieflex-row
aby elementy wewnątrz diva układały się jeden za drugimjustify-content-between
aby elementy wewnątrz umiejscowione były możliwie jak najbardziej od siebiep-3
tą klasą nadamy marginesy wewnętrzne
Drugi div będzie jednocześnie karuzelą, taką jak nasze zdjęcia, więc znowu kopiujemy z dokumentacji tą samą karuzelę po czym dodajemy do niej odpowiednie klasy:
card-body
ustali nam ospowiednie marginesy oraz wygląd tekstu
Usuwamy również wszystkie zdjęcia, gdyż na ich miejsce chcemy wstawić tekst i odnośnik.
Aby wszystko lepiej wyglądało podzielimy nasz tekst na tytuł i content, a poniżej umieścimy odnośnik i to powtarzammy w każdym z trzech slajdów.
<div class='h-100 d-flex flex-column justify-content-between'>
<div cless='flex-column d-flex'>
<h5 class='card-title d-inline'>Lorem</h5>
<p class='card-text'> Lorem ipsum dolor sit, amet consectetur adipisicing elit. Sit modi solut
corrupti magni sunt iste nulla.</p>
</div>
<a class="font-weight-bold" href="#">Buy now<i class="fas fa-angle-right ml-2"></i></a>
</div>
Teraz zajmiemy się przyciskami, za pomocą których będziemy mogli kontrolować naszą karuzelę. Do
wcześniej pominiętej sekcji .controls
dodajemy dwa divy, które podzielą nam miejsce
na przyciski i spiner odliczający czas do zmienienia się slajdu, a następnie używając font
awesome nadamy przyciskom postać przyjaznych dla oka strzałek.
<div class='controls d-flex p-3'>
<div class='control-buttons d-inline'>
<a class="close next-btn" aria-label="next"><i class="fas fa-angle-right m-1"></i></a>
<a class="close prev-btn" aria-label="prev"><i class="fas fa-angle-left m-1"></i></a>
</div>
<div class='control-loader'>
</div>
</div>
Część z loaderem zostawmy sobe na razie na później.
CSS
W naszym arkuszu stylów nie bedziemy musieli dużo pisać z racji tego, że większość właściwości zdefiniowaliśmy poprzez klasy w HTML.
Jedyne, co musimy zrobić, to nadać odpowiednie proporcje elementom w naszej karcie. Osobiście
uważam, że najlepiej wygląda, gdy obraz zajmuje 2/3 karty, a tekst pozostałe 1/3. Wykorzystamy tu
fakt, że nasza karta ma display:flex
, co pozwoli nam użyć właściwości
flex
definiującej, jak dużo miejsca ma zajmować dany element.
.carousel-card-image{
flex:2;
}
.carousel-right{
flex:1;
}
JavaScript
Teraz możemy się zająć prawdopodobnie najtrudniejszą częścią naszego projektu, czyli skryptem,
który zapiszemy w języku JavaScript, w pliku script.js
, który wcześniej stworzyliśmy.
Aby ułatwić sobie pracę użyjemy biblioteki jQuery.
W pierwszej kolejności stworzymy funkcję, która pozwoli nam na przewinięcie karuzeli w dowolnym
kierunku z dowolnego obiektu znajdującego się w naszej karcie. W tym celu wykorzystamy metodę
parents()
, aby z dowolnego elementu naszej karty znaleźć kartę główną, do której on
naeży, a następnie znajdziemy dzieci tej karty, które będą kolejno karuzelą ze zdjęciem oraz
karuzelą z tekstem. Gdy już to zrobimy, metodą carousel()
będziemy mogli przewijać
karuzelę do przodu lub do tyłu.
function carouselSwitch(direction, obj){
$('.carousel',$(obj).parents('.carousel-card')).carousel(direction);
}
Jak możecie zauważyć funkcja przyjmuje 2 zmienne: direction
przyjmuje wartość 'next' lub 'prev', która
definiuje kierunek, w którym chcemy poruszyć naszą karuzelę, natomiast zmienna obj
będzie przechowywała obiekt HTML, z którego wywołujemy tą funkcje (w większości przypadków będzie
to this).
Teraz możemy dodać tzw. obserwatory zdarzeń na nasze przyciski. Aby to zrobić dopisujemy do naszego skryptu następujący kod:
$('.next-btn').click(function(){
carouselSwitch('next', this);
})
$('.prev-btn').click(function(){
carouselSwitch('prev', this);
})
Teraz, gdy wrócimy na naszą stronę, ujrzymy w pełni funkcjonalne przyciski. W sekcji
controls
pozostało nam jeszcze jedno puste miejsce, którym właśnie teraz się
zajmiemy, umieszczając tam spiner zmieniający nam karty co określoną ilość czasu.
Dobrze się składa, bo niedawno zrobiłem projekt loaderów, które przydają się właśnie do takich
celów.
Po krótce opiszę jego sposób działania i wykorzystania w praktyce, abyście mogli posłużyć się tą
wiedzą w przyszłych projektach.
Spinner mojego autorstwa opiera się o narzędzie HTML'a 5 zwane canvas
. Służy ono do
'rysowania' po naszym dokumencie za pomocą metod w JavaScript.
Aby zaimplementować go do naszej strony, wpisujemy w diva z klasą .control-loader
następujący kod:
<canvas class="loader" width="20px" height="20px" data-color='#999A9C' data-interval="6000"
data-repeat='1' data-function="carouselSwitch('next', this.c)"></canvas>
Postaram się wytłumaczyć teraz krok po kroku do czego służy każdy atrybut
width
definiuje szerokośćheight
definiuje wysokośćdata-color
definiuje kolor spinneradata-interval
określa czas, jaki ma zająć spinnerowi zrobienie całego kółkadata-repeat
określa, czy załadowanie ma być jednorazowe (dla 0) lub powtarzane w nieskończoność (dla 1)data-function
zawiera funkcję, która ma być wywołana za każdym okrążeniem
Funkcja zawarta w data-function
wywołuje wcześniej stworzoną przez nas funkcję
carouselSwitch()
. Jako nasz drugi parametr podajemy tym razem
this.c
gdyż pod taką nazwą w skrypcie loadera znajduje się zmienna przechowująca
obiekt HTML naszego canvasa.
Aby zainicjować nasz loader, wklejamy do skryptu następujący kod:
class Loader{
constructor(c){
this.c=c;
this.ctx = c.getContext("2d");
this.time = parseInt(c.dataset.interval);
this.speed=20;
this.t=0;
this.lw = c.width/4
this.l = setInterval(this.draw.bind(this), this.speed)
}
draw(){
this.ctx.clearRect(0, 0, this.c.width, this.c.height)
if(!$(this.c).hasClass('paused')){
this.t+=this.speed;
}
if(this.t>this.time){
if(this.c.dataset.repeat!='1' && this.c.dataset.repeat!='true'){clearInterval(this.l)}
this.t=0;
eval(this.c.dataset.function)
}
this.ctx.beginPath()
this.ctx.arc(this.c.width/2, this.c.height/2, this.c.width/2-this.lw/2, 1.5*Math.PI, this.t/this.time*2*Math.PI+1.5*Math.PI)
this.ctx.lineWidth=this.lw
this.ctx.strokeStyle=this.c.dataset.color;
this.ctx.stroke()
this.ctx.closePath()
}
}
let loaders = $('.loader').toArray()
for(i in loaders){
new Loader(loaders[i])
}
Teraz nasza karta jest już niemal w pełni funkcjonalna, lecz jeszcze pod jednym aspektem można polepszyć jej działaie. Mianowicie gdy próbujemy przeczytać jakiś tekst na naszej karcie, może się zdarzyć, że przewinie się ona zanim zdążymy doczytać do końca. Sprawmy więc, że nakierowanie kursora na kartę wstrzymuje loader i pozwala nam na spokojne przeczytanie treści.
Najprostszym na to sposobem będzie dodanie obserwatorów zdarzeń na kartę aby wykrywała, gdy użytkownik nakieruje na nią kursor lub gdy z niej zjedzie.
$('.carousel-card').mouseenter(function (){
$('.loader', this).addClass('paused')
})
$('.carousel-card').mouseleave(function (){
$('.loader', this).removeClass('paused')
})
Powyższy skrypt nadaje loaderowi klasę paused, która zatrzymuje go, a co za tym - idzie nasza karta nie będzie się już samoistnie zmieniać.
Koniec
Karta, którą stworzyliśmy jest już funkcjonalna i gotowa do użycia na naszej stronie, a końcowy efekt powinien wyglądać w taki sposób.