Techniki CSS dla efektu marszczenia materiału

Przewodnik po różnych technikach efektu marszczenia za pomocą CSS i JavaScript

Niedawno musiałem zaimplementować efekt tętnienia od projektowania materiałów do aplikacji internetowej. I wtedy zdałem sobie sprawę, że nie mam pojęcia, jak to zostało wdrożone. To zaprowadziło mnie w podróż do studiowania istniejących wdrożeń, a nawet do opracowania zupełnie nowej techniki, która może być dla Ciebie przydatna.

Co to za efekt marszczenia?

Chwila, nie znasz efektu marszczenia z Material Design Google? Od ilu lat mieszkasz w jaskini?

Efekt marszczenia jest używany po naciśnięciu przycisku. Działa tak samo w przypadku interakcji myszy lub dotyku.

Pozycja, którą klikniesz lub dotkniesz przycisku, nazywa się punktem kontaktowym. Stamtąd wysyłana jest zmarszczka poruszająca się na zewnątrz, tracąca krycie, gdy rośnie, aż wypełni cały przycisk. Potem znika całkowicie.

Dynamika tego efektu falowania jest podobna do fal, które uzyskuje się po dotknięciu powierzchni cieczy lub po upuszczeniu skały do ​​jeziora.

Fale znajdziesz w Internecie

Po przeprowadzeniu badań mogłem znaleźć dwie główne techniki, które są używane do implementacji efektu tętnienia w aplikacjach internetowych.

Użycie :: po pseudoelemencie

Korzystając z tej techniki, pseudoelement przycisku po jest stylowany jako półprzezroczysty okrąg i animowany, aby rosnąć i zanikać. Przycisk kontenera musi mieć przepełnienie: ukryty, aby koło nigdy nie wypływało poza powierzchnię przycisku, i położenie: względne, aby ułatwić ustawienie okręgu w obrębie przycisku. Więcej szczegółów na temat tej techniki można przeczytać w tym artykule Ionuț Colceriu.

Jedną z wielkich zalet tej techniki jest to, że jest to czyste rozwiązanie CSS dla efektu tętnienia. Jednak efekt tętnienia zaczyna się zawsze od środka przycisku, a nie od punktu kontaktu. To nie jest najbardziej naturalna informacja zwrotna.

Można to ulepszyć, używając JavaScript do przechowywania punktu kontaktu i używania go do pozycjonowania tętnienia. Właśnie to zrobił material.io dla swojego elementu tętnienia sieci. Wykorzystuje zmienne CSS do przechowywania punktu kontaktu, a pseudoelement :: after używa tych zmiennych do pozycjonowania.

Korzystanie z elementów potomnych

Zasadniczo w tej technice zastosowano tę samą strategię jak poprzednio. Ale zamiast pseudoelementu dodaje element span wewnątrz przycisku, który można następnie pozycjonować za pomocą JavaScript. Technikę tę opisał w tym artykule Jhey Tompkins.

Najprostsza implementacja tworzy zakres dla każdego kliknięcia przycisku i wykorzystuje pozycję myszy na zdarzeniu click, aby zmienić pozycję zakresu. Animacja CSS powoduje, że zakres rośnie i zanika, aż staje się w pełni przezroczysty. Możemy usunąć rozpiętość z DOM po zakończeniu animacji lub po prostu zostawić ją pod dywanem - nikt tak naprawdę nie zauważy przezroczystej rozpiętości.

Znalazłem inną odmianę tego, w której elementem potomnym jest svg zamiast span, a svg jest animowany przez JavaScript. Ta odmiana jest wyjaśniona przez Dennisa Gaebela, ale w gruncie rzeczy wydaje się być taka sama i być może pozwala na stosowanie skomplikowanych kształtów i efektów SVG.

Problem z przesyłaniem danych wejściowych

Obie opisane powyżej techniki wydają się świetne. Ale tak się dzieje, gdy próbowałem zastosować je do elementów wejściowych za pomocą type = submission:

Dlaczego nie działają?

Element wejściowy jest zastąpionym elementem. Krótko mówiąc, oznacza to, że niewiele można zrobić z tymi elementami w odniesieniu do DOM i CSS. W szczególności nie mogą mieć elementów potomnych ani pseudoelementów. Teraz jest jasne, dlaczego te techniki zawodzą.

Jeśli więc korzystasz z Material Design, lepiej trzymać się z dala od danych wejściowych [type = submission] i trzymać się elementów przycisków. Lub po prostu czytaj dalej.

Dodawanie zmarszczek w celu przesłania danych wejściowych

W aplikacji internetowej, nad którą pracowałem, mieliśmy już wiele przycisków przesyłania. Zmiana ich wszystkich na inny element wymagałaby dużo pracy i dużego ryzyka uszkodzenia arkuszy stylów i logiki JavaScript. Musiałem więc wymyślić, jak dodać fale do istniejących przycisków przesyłania.

Korzystanie z pojemnika do owijania

Szybko zorientowałem się, że mogę owinąć przycisk wysyłania wewnątrz elementu bloku śródliniowego i użyć elementu bloku śródliniowego jako powierzchni tętnienia. Oto krótkie demo:

Chociaż podoba mi się to rozwiązanie ze względu na jego prostotę, wciąż wymagało to ode mnie zmiany znaczników w zbyt wielu miejscach. Wiedziałem, że będzie to delikatne rozwiązanie - nowi programiści pojawią się w projekcie i utworzą przyciski przesyłania bez odpowiedniego zawijania ich na marszczonej powierzchni. Dlatego szukałem innych rozwiązań, które nie wymagałyby zmiany DOM.

Gradienty promieniowe

Składnia gradientu radialnego pozwala mi kontrolować zarówno środek, jak i rozmiar gradientu. Oczywiście pozwala mi także kontrolować kolor gradientu, w tym kolory półprzezroczyste. I nigdy nie przepełnia elementu, do którego został zastosowany. Wygląda więc na to, że już robi wszystko, czego potrzebuję!

Nie tak szybko… brakuje jednej rzeczy: właściwość obrazu tła nie jest animowana. Nie mogłem sprawić, by gradient powiększał się i zanikał do przezroczystości za pomocą animacji CSS. Udało mi się sprawić, by wzrosła, animując właściwość wielkości tła, ale to było wszystko, co mogłam zrobić.

Próbowałem kilku innych rzeczy, takich jak wygaszanie koła jako animowanego obrazu (w formacie apng) i zastosowałem go jako obraz tła. Ale wtedy nie mogłem kontrolować, kiedy pętla obrazu zaczyna się i kończy.

Wreszcie rozwiązanie z JavaScript

Czego nie możesz zrobić w CSS, możesz to zrobić w JavaScript. Po spędzeniu więcej czasu, niż jestem skłonny przyznać, próbując uzyskać ten efekt przy użyciu animacji CSS, po prostu poddałem się i postanowiłem napisać animację w JavaScript.

Zacząłem od powyższego rozwiązania z gradientem radialnym i użyłem window.requestAnimationFrame do płynnej animacji gradientu radialnego, rosnącego i zanikającego. Oto moje ostateczne rozwiązanie:

Wniosek

Dlatego możliwe jest uzyskanie efektu falowania na przyciskach przesyłania, ale nie tylko w CSS.

Nie mogłem znaleźć tej techniki udokumentowanej w dowolnym miejscu w sieci, dlatego nazywam ją własną. Technika marszczenia Leonarda nie wymaga zmian w DOM i działa na każdym elemencie, ponieważ nie opiera się na pseudoelementach ani elementach potomnych. Jednak nie jest to idealne rozwiązanie.

Po pierwsze, jest wydajność. Animując gradient za pomocą JavaScript, tracisz wiele optymalizacji przeglądarki. Ponieważ jednak jedyną zmienianą właściwością jest obraz w tle, podejrzewam, że przeglądarki nie będą musiały się przepływać, a po prostu wymagają ponownego zastosowania stylów i odmalowania elementu. W praktyce tak właśnie się dzieje, a wydajność jest naprawdę dobra. Wyjątkiem od tego oświadczenia jest Firefox Mobile, który z jakiegoś powodu nie nadąża za animacją. (edycja: animacja jest płynna w nowoczesnych wersjach Firefox Mobile)

Po drugie, technika wykorzystuje właściwość obrazu tła przycisku. Jeśli twój projekt wymaga, aby przyciski miały obraz zastosowany na tle, efekt marszczenia zastąpiłby to. Jeśli naprawdę potrzebujesz tego obrazu w swoim projekcie, JavaScript można zmodyfikować, aby narysować gradient promieniowy na istniejącym obrazie tła.

Po trzecie, nie działa to w Internet Explorerze. Nie widzę jednak żadnego powodu, dla którego miałby nie działać z IE10 i nowszymi wersjami. Może dlatego, że IE używa innej składni gradientu radialnego. Ale kogo to obchodzi w dzisiejszych czasach IE? (edycja: ta metoda działa bez żadnych problemów w przeglądarce Internet Explorer 11)