Vytvoření 3D React Carousel

Je ve mně něco, co je ohromující, ale krásné 3D rozhraní. A nezáleží na tom, zda jsou funkční jako nabídka funkcí gyroskopu, technologické demonstrátory jako úžasné demo periodické tabulky od slavných nebo jde o umělecké znázornění posouvající limity současné technologie CSS, jako jsou pera od Ana Tudor nebo Hakim El Hattab. Miluji je všechny a hledám záminku, abych něco podobného použil ve svých aplikacích.

Před několika měsíci jsem vyzkoušel React, ohromilo mě, jak rychle jsem s ním produktivní, a umožnilo mi to soustředit se na psaní aplikace. Rychle jsem přizpůsobil téma bootstrapu, řízená interaktivita a rozhraní aplikace bylo hotovo během okamžiku. Cítil jsem však, že něco chybí. Jakmile bylo možné provést základní vzhled a dojem s tak malým úsilím, malý hlásek ve mně se cítil nespokojený. Branky byly posunuty, chtěl jsem animaci.

Výuka lana

Rozhodl jsem se vytvořit 3D kolotoč s Reactem, jako samostatné cvičení toho, jak framework funguje s malou, ale samoudržující komponentou. Moje první pravidlo bylo, že se animace neresetuje, když přidám a odeberu prvky, změním rozvržení nebo otočím karusel. Toto tvrdé omezení, které chybělo i v komerčních karuselech, způsobilo zásadní rozdíl v designu.

Nejprve jsem se podíval na React ReactCSSTransitionGroup, ale nějak mi to nepřišlo správné a komentáře na fórech ohledně přidávání a odebírání prvků byly děsivé. Začal jsem tedy pracovat ručně pomocí tutoriálu Dave DeSandro ohledně 3D transformací. Kreslení karuselu s navrhovaným rozložením nebylo příliš těžké a podařilo se mi bez větších problémů transformovat pravidla CSS DeSandro do funkcí JavaScriptu.

Zobrazit ukázku

Dosažení 3D efektu

Kolotoč se skládá ze čtyř prvků:

1. Část, která obsahuje obrázky a ovládací prvky, má statickou délku a šířku, obsahuje perspektivu a její relativní do nadřazeného prvku.

// Static styling
.react-3d-carousel { 
    width: 400px; 
    height: 300px; 
    position: relative; 
    perspective: 1000px;
}

2. A div obsahující zobrazené obrázky, jeho position je absolute a má transform-style: preserve-3d vlastnictví. Tento prvek je přeložen přes osu Z, aby byl karusel ve správné vzdálenosti od diváka.

// Static styling
.react-3d-carousel .carousel {  // image container
   width: 100%; 
   height: 100%; 
   position: absolute; 
   transform-style: preserve-3d;
} 
// Dynamic styling  example
  transform:translateZ(-347px);

Vzdálenost rozvržení hranolu se vypočítá jako apotém mnohoúhelníku. Pro klasické rozvržení kolotoče jsem experimentoval s několika vzorci, dokud jsem nevytvořil něco, co vypadalo v pořádku.

function apothem(width, sides) { 
     return Math.ceil(width / (2 * Math.tan(Math.PI / sides))); 
}
function magic(width, sides) {        
    return Math.round(width * Math.log(sides))    
}

3. Značka obrázku představuje jeden zobrazený obrázek. Je dynamicky stylizován podle poskytnutého rozvržení a stavu animace. Protože jsou definice funkcí příliš velké, zkontrolujte soubor rozvržení pro odpovídající výpočet. Níže uvádím statický styl s příkladem vygenerovaného stylu prvku z funkcí rozložení.

// Static styling
.react-3d-carousel .carousel figure { // single image
   display: block; 
   position: absolute; 
   width: 400px; 
   height: 300px; 
}
// Dynamic styling
// Prism layout figure example styling
transform: rotateY(1.047rad) translateX(0px) translateZ(347px);
opacity:  1;
// Classic layout figure example styling
transform: rotateY(0rad) translateX(620.94px) translateZ(358.5px); opacity: 1;

4. Ovládací prvky - V současné době jsou ovládací prvky staticky styly používající dvě bílé šipky jako pozadí, pokud máte jiné preference, jednoduše změňte CSS do souboru style.css. Níže je úryvek představující směrové šipky.

.react-3d-carousel   .prev:before { 
      content: url("chevron_left_white.png");
}
.react-3d-carousel    .next:before { 
      content: url("chevron_right_white.png");
}

Přidání rozvržení

Pokud chcete přidat další rozvržení, řekněme to, které se používá v Royal 3D karuselu nebo hvězdicovou topologii Ultimate 3D karuselu, musíte implementovat dvě funkce, které vypočítají vzdálenost od diváka a pozici každé postavy.

// Receives width of the image and number of sides returns
// distance from the viewer to the carousel
function distance(width, sides) {
// Receives width of the image, images and initial rotation
// of the carousel, return array of all images with their
// corresponding transformations & rotations
function figures(width, images, initial) {

To umožňuje, aby byl karusel rozšiřitelný o další rozvržení, ale uživatel bude muset najít způsob, jak rozvržení vyjádřit jako funkci.

Správa stavu

Na druhou stranu správa stavu byla od začátku problematická. Karusel má mezistav, když se otáčí a když přidává nebo ubírá strany, které jsou horší o možnost měnit rozložení za chodu, což zcela mění vzhled karuselu. Můj první přístup byl použít animační knihovnu nebo engine ke správě stavu. Existovalo několik pěkných knihoven, které mi mohly usnadnit život, ale protože karusel byl součástí, byl jsem velmi dobře obeznámen s tím, jak nutit lidi přidávat závislosti, které jsou mnohem větší než funkce, které skutečně potřebují. Protože se mi RxJS v tuto chvíli nezdálo tak těžké, provedl jsem svou první iteraci pomocí portu Paula Taylora z funkcí ulehčení Roberta Pennera a pomocí Ramda pro funkční úlohy na nízké úrovni.

Stav karuselu je uložen v souboru depa, který umožňuje uživateli předávat nové vlastnosti a/nebo otáčet karuselem.

Odebírání závislostí

Kód fungoval, ale byl to nepořádek a RxJS a Ramda mi stále připadali jako příliš velké zavazadlo, takže ve druhé iteraci jsem extrahoval všechny funkce, které jsem potřeboval, a přefaktoroval kód . Možnost měnit rozložení za chodu mě přivedla k velmi funkčnímu designu. Přímá práce s requestAnimationFrame odhalila některé velmi zajímavé problémy, například proč je můj kód volán pouze jednou.

Publikování a čištění

Moje komponenta byla připravena, takže jsem sbalil demo, které bylo použito při vývoji jako příklad a publikoval jsem ho na Github. Zpočátku bylo mnoho problémů, které jsem nepředvídal, na většinu z nich poukázal Juho Vepsäläinen se svými užitečnými radami, jak je opravit. Byl jsem velmi překvapen, když jiný uživatel nebyl schopen nainstalovat karusel. Ale předpokládám, že chyby přicházejí s uživateli, nakonec se mi je podařilo opravit a udělat karusel použitelný.

Zobrazit ukázku

Závěr

Kausel představuje miniaturní příklad jednosměrného toku dat a schopnosti řídit přechodný stav. Je to jen malý krůček k další generaci uživatelských rozhraní, kde bude páteří interakce namísto pastvy pro oči, kterou si uživatel může užít, animace. S růstem rychlosti zpracování v hardwaru jsou prohlížeče připraveny, zbytek je na softwaru.

Zdroj můžete najít na github a prohlédnout si hotový karusel na codepen. Zkuste změnit rozložení, náběhové funkce, počet stran a samozřejmě otočte karusel.