Techniky CSS pro efekt zvlnění materiálu

Průvodce různými technikami zvlnění pomocí CSS a JavaScript

Nedávno jsem musel implementovat efekt zvlnění z materiálového designu do webové aplikace. A pak jsem si uvědomil, že netuším, jak to bylo implementováno. To mě vedlo k cestě ke studiu stávajících implementací a dokonce přišel s úplně novou technikou, která by pro vás mohla být užitečná.

Co je to zvlnění?

Počkejte, neznáte zvlnění z materiálového designu Google? Žili jste v jeskyni už mnoho let?

Efekt zvlnění se používá, když stisknete tlačítko. Funguje stejným způsobem pro interakci myši nebo dotyku.

Poloha, na kterou klepnete nebo se dotknete tlačítka, se nazývá kontaktní místo. Odtud se zvlnění posílá směrem ven a ztrácí neprůhlednost, protože se zvětšuje, dokud nevyplní celé tlačítko. Pak úplně zmizí.

Dynamika tohoto zvlnění je podobná vlnkám, které získáte, když se dotknete tekutého povrchu nebo když spadnete skálu do jezera.

Zvlnění, které najdete na webu

Po provedení nějakého výzkumu jsem našel dvě hlavní techniky, které se používají k implementaci zvlnění na webových aplikacích.

Pomocí :: po pseudoprvku

Při použití této techniky je pseudoprvek tlačítka :: po stylizovaný jako poloprůhledný kruh a animovaný pro růst a vyblednutí. Tlačítko kontejneru musí mít přetečení: skryté, aby kruh nikdy přetékal mimo povrch tlačítka a polohu: relativní, aby bylo snadné umístit kruh do tlačítka. Více informací o této technice si můžete přečíst v tomto článku od Ionuț Colceriu.

Jednou z velkých věcí na této technice je, že se jedná o čisté řešení zvlnění CSS. Efekt zvlnění však začíná vždy od středu tlačítka, místo od bodu kontaktu. To není nejpřirozenější zpětná vazba.

To by mohlo být vylepšeno pomocí JavaScriptu k uložení kontaktního místa a jeho použití k umístění zvlnění. To je přesně to, co material.io udělal pro svou komponentu zvlnění webu. K uložení kontaktního bodu používá proměnné CSS a pseudoprvek :: :: after tyto tyto proměnné používá pro určování polohy.

Použití podřízených prvků

Tato technika v podstatě používá stejnou strategii jako dříve. Namísto pseudo-elementu však do tlačítka přidá rozpínací prvek, který pak lze umístit pomocí JavaScriptu. Tato technika je popsána v tomto článku Jhey Tompkins.

Nejjednodušší implementace vytvoří rozpětí pro každé kliknutí na tlačítko a pomocí pozice myši na události kliknutí změní polohu rozpětí. Animace CSS způsobuje, že rozpětí roste a mizí, dokud není plně transparentní. Jakmile se animace dokončí, můžeme se rozhodnout, že rozpětí z DOM odstraníme, nebo to necháme jen pod kobercem - nikdo si opravdu nevšimne průhledného rozpětí visícího kolem.

Našel jsem další variantu, na které je podřízený prvek svg místo rozpětí a svg je animován skriptem JavaScript. Tuto variantu vysvětluje Dennis Gaebel, ale v podstatě se zdá být stejná a možná umožňuje použití složitých tvarů a efektů SVG.

Problém s odesláním vstupů

Obě výše popsané techniky se zdají skvělé. Ale to se stane, když jsem se je pokusil použít na vstupní prvky s typem = předložit:

Proč nepracují?

Vstupním prvkem je nahrazený prvek. Zkrátka to znamená, že s těmito prvky můžete dělat jen velmi málo, pokud jde o DOM a CSS. Konkrétně nemohou mít podřízené prvky ani žádné pseudo elementy. Nyní je jasné, proč tyto techniky selhávají.

Pokud tedy používáte Design materiálu, je lepší držet se dál od vstupu [typ = odeslat] a držet se tlačítek. Nebo jen čtěte dál.

Přidání vlnky k odeslání vstupů

Na webové aplikaci, na které jsem pracoval, jsme již měli spoustu tlačítek pro odeslání. Změna všech z nich na jiný prvek by vyžadovala spoustu práce a vysoké riziko porušení stylů stylů a logiky JavaScriptu. Takže jsem musel přijít na to, jak přidat vlnky do stávajících tlačítek pro odeslání.

Použití balicího obalu

Rychle jsem si uvědomil, že bych mohl zabalit tlačítko Odeslat do prvku vloženého bloku a použít prvek vloženého bloku jako povrch zvlnění. Zde je rychlé ukázky:

I když se mi toto řešení líbí pro jeho jednoduchost, stále mě vyžadovalo, abych změnil označení na příliš mnoha místech. A věděl jsem, že to bude křehké řešení - do projektu vstoupí noví vývojáři a vytvoří tlačítka pro odeslání, aniž by je řádně zabalili do zvlněného povrchu. Stále jsem hledal jiná řešení, která nevyžadují změnu DOM.

Radiální přechody

Syntaxe radiálního gradientu mi umožňuje ovládat jak střed, tak velikost gradientu. Samozřejmě mi to také umožňuje ovládat barvu přechodu, včetně poloprůhledných barev. A nikdy nepřetéká prvek, na který se vztahuje. Zdá se tedy, že již dělá vše, co potřebuji!

Ne tak rychle ... chybí jedna věc: vlastnost pozadí-obrázek není animovatelná. Pomocí animací CSS jsem nemohl dosáhnout toho, aby se gradient rozrůstal a zeslaboval na průhledný. Zvládl jsem, aby se rozrostl animací vlastnosti velikosti pozadí, ale to bylo všechno, co jsem mohl udělat.

Vyzkoušel jsem několik dalších věcí, například mizející kruh jako animovaný obrázek (ve formátu apng) a použil jsem ho jako obrázek na pozadí. Ale pak jsem nemohl ovládat, kdy obrazová smyčka začala a skončila.

Nakonec řešení s JavaScriptem

Co v CSS nemůžete udělat, můžete to udělat v JavaScriptu. Poté, co jsem strávil více času, než jsem ochoten připustit, abych se pokusil o to, aby tento efekt fungoval pomocí animací CSS, jsem se prostě vzdal a rozhodl se napsat animaci do JavaScriptu.

Začal jsem s řešením radiálního přechodu výše a pomocí okna.requestAnimationFrame vytvořil tekutou animaci radiálního gradientu, rostl a mizel. Zde je moje konečné řešení:

Závěr

Je tedy možné mít zvlnění na tlačítka pro odeslání, ne pouze u CSS.

Tuto techniku ​​jsem nemohl najít nikde na webu, takže ji nazývám svou vlastní. Technika zvlnění Leonarda nevyžaduje změny DOM a funguje pro jakýkoli prvek, protože se nespoléhá na pseudo-prvky nebo podřízené prvky. Není to však bezchybné řešení.

Nejprve je tu výkon. Animací přechodu pomocí JavaScriptu ztratíte spoustu optimalizací prohlížeče. Ale protože jedinou změnou vlastností je obrázek na pozadí, měl bych podezření, že prohlížeče by se nemusely přeformátovat, a vyžadovalo by pouze opakované použití stylů a překreslení prvku. V praxi se to přesně děje a výkon je opravdu dobrý. Výjimkou z tohoto příkazu je Firefox Mobile, který z nějakého důvodu s animací nedrží krok. (úprava: animace je u moderních verzí prohlížeče Firefox Mobile bezproblémová)

Za druhé, technika používá vlastnost tlačítka na pozadí. Pokud váš návrh vyžaduje, aby tlačítka měla na pozadí použit obrázek, zvlnění by to potlačilo. Pokud opravdu potřebujete tento obrázek ve svém návrhu, pak by se JavaScript mohl upravit tak, aby nakreslil radiální gradient na horní část existujícího obrázku na pozadí.

Za třetí, zdá se, že to nefunguje v aplikaci Internet Explorer. Nevidím však žádný důvod, proč by neměl fungovat s IE10 a vyššími. Možná je to proto, že IE používá odlišnou syntaxi pro radiální gradient. Ale koho dnes zajímá IE? (upravit: tato metoda funguje bez problémů v aplikaci Internet Explorer 11)