CSS transition a vytvoření jednoduchého JS carouselu

Wed, 25 Nov 2015 15:15:42 +1100

V minulém článku jsem sliboval, že bude další, ve kterém najdete návod na jednoduchý carousel vytvořený za pomoci JavaScriptu a CSS transition. Tak tady je. Pokud si na stránce zascrollujete trochu níž a vyhledáte v pravém sloupci "Mikroblog" a "Nejnovější články", tak přesně to bude výsledek.

Pokud se vám metoda fade in/fade out nelíbí, v druhé části článku se můžete podívat, jak slider upravit na posuv ze strany na stranu. Jak potom dostat obě metody do jediné funkce, to si můžete zkusit sami; funkce to budou opravdu jednoduché a jejich úprava nebude nijak složitá. JavaScript zde bude ještě jednodušší než styly; takže asi taková bude náročnost. Ale i tak si všechno krok po kroku projedeme. Se vším nám pomůže knihovna jQuery.

První slider

1. HTML

Začneme jak jinak, než od HTML kódu. Jak vidíte, opravdu ho není hodně. První důležitá věc je resizovací obrázek: díky němu bude celý objekt pěkně responzivní, díky němu můžeme použít všude absolutní pozice. Je to jenom průhledné png v rozměrech 300x200 pixelů, takže celé to bude vždy v poměru 3:2. Šipky jsou pak samozřejmě ovládací prvky. Prvnímu elementu rovnou nastavíme třídu active, která bude mít důležitou úlohu nejen ve stylech, ale také v samotné obsluze. Toť vše. Jednotlivých prvků ".item" tam může být, kolik jen budeme potřebovat.







Nadpis 1


Nadpis 2


Nadpis 3




2. CSS

Styly zde samozřejmě nebudu uvádět úplně všechny, ale jenom ty nejdůležitější, sloužící ke správnému zobrazení a funkcionalitě. A přijde řeč i na transition. Právě tato vlastnost nám bude celou mašinu pohánět, navíc se postará i o pěkný hover efekt.

.slider {position:relative;}
.slider .resizer {display:block;margin:0;width:100%;}

.slider .inner {position:absolute;width:100%;height:100%;top:0;left:0;overflow:hidden;}
.slider .inner .item {
	position:absolute;top:0;left:0;padding:0;margin:0;width:100%;height:100%;
	z-index:0;opacity:0;transition:300ms; -webkit-transition:300ms;
	background-position:50% 66.6%;background-size:100% auto;
}
.slider .inner .item.active {z-index:10;opacity:1;}
.slider .inner .item:hover {background-size:105% auto;}

Zde už by od pohledu mělo být jasné, jak to celé dopadne. Hlavnímu divu dáme relativní pozici, čímž můžeme vše uvnitř roztáhnout na 100% šířky i výšky, takže každý jeden slide bude přizpůsobený našemu resizovacímu obrázku. Když se podíváte na definice prvku ".item:hover", uvidíte, že background-size, tedy velikost pozadí se také bude měnit. A právě díky transition to bude plynule. Přidáním třídy ".active" se pak změní průhlednost z 0 na 1 a z-index, což bude změna viditelného slidu. Další vlastnosti zde popisovat už nebudu, jedná se o totiž pouze o doplňkové designové prvky, o kterých tento článek není.

3. JavaScript

Ani JavaScriptu nebude mnoho. K čemu zbytečně stahovat megové knihovny na carousely, které si stejně nedokážeme přizpůsobit, protože k tomu chybí dokumentace? K čemu používat monstrózní řešení, když tohle je otázkou 15 minut?

Máme:

2 parametry

1 kontrolu

2 funkce na posun doleva a doprava

2 napojení těchto funkcí

1 automatické spuštění

function MiniSlider(slider_element,auto_time){
	var autoInt = null;

	if(!slider_element.find('.inner').size()){
		return false;
	}

	var parent = slider_element.find('.inner');
	parent.find('.item:first-child').addClass('active');

	var moveItRight=function(){
		var nxt = parent.find('.item.active').next();
		if(!nxt.size()){
			nxt = parent.find('.item:first-child');
		}
		parent.find('.item.active').removeClass('active');
		nxt.addClass('active');
	};

	var moveItLeft=function(){
		var prv = parent.find('.item.active').prev();
		if(!prv.size()){
			prv = parent.find('.item:last-child');
		}
		parent.find('.item.active').removeClass('active');
		prv.addClass('active');
	};

	slider_element.find('.shipka.shipka-right').click(function(){
		clearInterval(autoInt);
		moveItRight();
		return false;
	});

	slider_element.find('.shipka.shipka-left').click(function(){
		clearInterval(autoInt);
		moveItLeft();
		return false;
	});

	autoInt = setInterval(function(){
		moveItRight();
	},auto_time);
}

new MiniSlider($('.slider'), 5000);

Jak to tedy celé funguje?

Úplně snadno. Funkce najde prvek s třídou active a hledá prvek následující (respektive předcházející). Pokud ho nenajde, vezme první (respektive poslední) element. Jednu třídu active odstraní, druhou přidá. Tím se změní průhlednost a transition nám z toho udělá plynulý efekt. Toť vše. Zde se můžete podívat na výsledek:

Ukázka: slider_sample.html
ZIP ke stažení: slider.zip

Druhý Slider

V druhé ukázce si slider trochu upravíme tak, aby objekty posouvaly ze strany na stranu. Na to mám sice hotové už poměrně komplexní řešení, to zde ale prezentovat nemohu. Navíc je to dost šílený výtvor a já raději píšu o věcech jednoduchých.

Můžeme nastavit vnitřnímu divu šířku podle počtu divů a posouvat jenom left či right vždy o jednu obrazovku. Na začátek a konec bychom pak museli zkopírovat poslední a první slide a navíc počítat, kdy je slider na konci a přehodit ho zase na začátek. Toto řešení je dobré v tom, že budeme mít slider nachystaný na větší počet různých chování, ale tím to bude pak složitější.

Jenže my to uděláme jinak, jednodušeji. Vždy jenom zaměříme další prvek co je na řadě, tento a aktuální položíme vedle sebe a pak oba posuneme. Po ukázce kódu to bude asi trochu jasnější. Toto řešení ale přinese jistá drobná úskalí, ale to si popíšeme až pod ukázkou JS kódu.

1. CSS

HTML kód zůstane, podíváme se tedy, co se změnilo ve stylech. Tam bude jiná definice prvku ".item". Transition omezíme pouze na pozadí, zbytek už bude probíhat na úrovni JavaScriptu. Prvkům nastavíme výchozí pozici o jednu obrazovku doleva, prvnímu pak left:0. Tím jsme ve stylech hotovi.

.slider .inner .item {
	position:absolute;top:0;left:-100%;padding:0;margin:0;width:100%;height:100%;
	z-index:0;transition:background 300ms; -webkit-transition:background 300ms;
	background-position:50% 66.6%;background-size:100% auto;
}
.slider .inner .item.active {}
.slider .inner .item:first-child {left:0;}
.slider .inner .item:hover {background-size:105% auto;}

2. JavaScript

Třídě přidáme další parametr, kterým bude délka animace. Už totiž není nastavená ve stylech. Dále už jenom rozšíříme funkce "moveLeft" a "moveRight". Zde už transition nebude ovládat posuv, zde využijeme klasické metody jQuery.animate(). Zjednodušeně to bude fungovat asi takto: před spuštěním posuvu seřadíme aktuální a následující vedle sebe a potom oba posuneme. Od směru se samozřejmě odvíjí souřadnice "left". Takto to zní jednoduše (a ono také je), ale jsou tu dvě věci, na které je potřeba myslet. Dřív, než budu cokoli přehazovat a posouvat, musím vše poctivě zresetovat. Nastavím správné pozice, z-indexy, stopnu animace. Tím ošetřím potenciální zběsilé klikání na šipku.

Další záludnost je pak samotný průběh dvou animací ve stejný okamžik: často se totiž stane, že se jedna z nich o pár milisekund zpozdí - výsledkem je pak takové bílé probliknutí mezi obrázky. Na řešení půjdeme od lesa: stačí prostě odjíždějící slide opozdit. Člověk to ani nepostřehne a my se zbavíme se nežádoucího efektu.

function MiniSlider(slider_element,auto_time,anim_time){

	var moveItRight=function(){
		var act = parent.find('.item.active');
		var nxt = parent.find('.item.active').next();
		if(!nxt.size()){
			nxt = parent.find('.item:first-child');
		}

		parent.find('.item').css({zIndex:0,left:'100%'}).stop(true,true);

		act.stop(true,true).css({zIndex:10,left:0});
		nxt.stop(true,true).css({zIndex:10});

		act.animate({left:'-100%'},anim_time+10).removeClass('active');
		nxt.animate({left:0},anim_time).addClass('active');
	};

	var moveItLeft=function(){
		var act = parent.find('.item.active');
		var prv = parent.find('.item.active').prev();
		if(!prv.size()){
			prv = parent.find('.item:last-child');
		}

		parent.find('.item').css({zIndex:0,left:'-100%'}).stop(true,true);

		act.stop(true,true).css({zIndex:10,left:0});
		prv.stop(true,true).css({zIndex:10});

		act.animate({left:'100%'},anim_time+10).removeClass('active');
		prv.animate({left:0},anim_time).addClass('active');
	};

}

new MiniSlider($('.slider'), 5000, 500);

A máme hotovo. Celá funkce je na pár desítek řádků, snadno pochopitelná, snadno rozšířitelná. Netřeba stahovat gigantické knihovny. Na závěr bychom ještě mohli obě třídy sloučit tak, aby další parametr určoval, jaký typ efektu bude uplatněn. To už ale nechám na vás, ať se také něco naučíte sami :-)

Ukázka: slider_sample.html
ZIP ke stažení: slider_mover.zip