CSS-technieken voor materiaalrimpelingseffect

Een gids voor verschillende technieken voor het rimpeleffect met behulp van CSS en JavaScript

Ik moest onlangs het rimpeleffect van materiaalontwerp in een webtoepassing implementeren. En toen besefte ik dat ik geen idee had hoe dat werd geïmplementeerd. Dit leidde me naar een reis om bestaande implementaties te bestuderen en zelfs met een geheel nieuwe techniek te komen die voor u nuttig zou kunnen zijn.

Wat is dit rimpeleffect?

Wacht, u kent het rimpeleffect van het materiaalontwerp van Google niet? Woon je al jaren in een grot?

Het rimpeleffect wordt gebruikt wanneer u op een knop drukt. Het werkt op dezelfde manier voor muis- of aanraakinteracties.

De positie waarop u klikt of de knop aanraakt, wordt het contactpunt genoemd. Vanaf daar wordt een rimpel verzonden die naar buiten beweegt en de dekking verliest naarmate deze groter wordt totdat deze de hele knop vult. Dan verdwijnt het volledig.

De dynamiek van dit rimpeleffect is vergelijkbaar met de rimpelingen die u krijgt wanneer u een vloeistofoppervlak aanraakt of wanneer u een rots in een meer laat vallen.

De rimpelingen die u op internet zult vinden

Na wat onderzoek te hebben gedaan, kon ik twee hoofdtechnieken vinden die worden gebruikt voor het implementeren van het rimpeleffect op webapplicaties.

Gebruiken :: na pseudo-element

Met deze techniek wordt het :: after pseudo-element van de knop gestileerd als een semi-transparante cirkel en geanimeerd om te groeien en vervagen. De containerknop moet een overloop hebben: verborgen zodat de cirkel nooit buiten het oppervlak van de knop en positie overstroomt: relatief om het gemakkelijk te maken om de cirkel binnen de knop te plaatsen. U kunt meer details over deze techniek lezen in dit artikel van Ionuț Colceriu.

Een van de geweldige dingen van deze techniek is dat het een pure CSS-oplossing is voor het rimpeleffect. Het rimpeleffect begint echter altijd vanuit het midden van de knop, in plaats van het contactpunt. Dat is niet de meest natuurlijke feedback.

Het kan worden verbeterd door JavaScript te gebruiken om het contactpunt op te slaan en het te gebruiken om de rimpel te positioneren. Dat is precies wat material.io heeft gedaan voor hun webrimpelingcomponent. Het gebruikt CSS-variabelen om het contactpunt op te slaan, en het :: after pseudo-element gebruikt deze variabelen voor positionering.

Onderliggende elementen gebruiken

In wezen gebruikt deze techniek dezelfde strategie als voorheen. Maar in plaats van een pseudo-element, voegt het een span-element binnen de knop toe, dat vervolgens via JavaScript kan worden geplaatst. Deze techniek wordt in dit artikel beschreven door Jhey Tompkins.

De eenvoudigste implementatie maakt een reeks voor elke klik op de knop en gebruikt de muispositie bij de klikgebeurtenis om de positie van de reeks te wijzigen. Een CSS-animatie laat het bereik groeien en vervagen totdat het volledig transparant wordt. We kunnen ervoor kiezen om het bereik van de DOM te verwijderen zodra de animatie is voltooid, of het gewoon onder het tapijt te laten staan ​​- niemand zal echt een transparant bereik opmerken dat rond hangt.

Ik heb een andere variant hiervan gevonden, waarop het onderliggende element een svg is in plaats van een spanwijdte, en de svg is geanimeerd via JavaScript. Deze variatie wordt verklaard door Dennis Gaebel, maar lijkt in essentie hetzelfde te zijn en misschien complexe SVG-vormen en -effecten toe te staan.

Een probleem met de invoer van gegevens

Beide hierboven beschreven technieken lijken geweldig. Maar dit is wat er gebeurt wanneer ik probeerde ze toe te passen op invoerelementen met type = submit:

Waarom werken ze niet?

Het invoerelement is een vervangen element. Kort gezegd betekent dit dat u met die elementen weinig kunt doen, met betrekking tot DOM en CSS. Concreet kunnen ze geen onderliggende elementen hebben en ook geen pseudo-elementen. Nu is het duidelijk waarom deze technieken falen.

Dus als u Material Design gebruikt, is het beter om weg te blijven van invoer [type = submit] en u aan knopelementen te houden. Of blijf gewoon lezen.

Rimpelingen toevoegen om invoer in te dienen

In de webtoepassing waaraan ik werkte, hadden we al veel verzendknoppen. Om ze allemaal te veranderen in een ander element zou veel werk nodig zijn, en een groot risico op het breken van stylesheets en JavaScript-logica. Dus moest ik uitzoeken hoe ik rimpelingen kon toevoegen aan de bestaande verzendknoppen.

Gebruik een wikkelcontainer

Ik realiseerde me snel dat ik de knop Verzenden in een inline-block-element kon wikkelen en het inline-block-element als rimpeloppervlak kon gebruiken. Hier is een korte demo:

Hoewel ik deze oplossing vanwege de eenvoud leuk vind, moest ik de markup op te veel plaatsen wijzigen. En ik wist dat het een breekbare oplossing zou zijn - nieuwe ontwikkelaars zouden bij het project komen en indienknoppen maken zonder ze op de juiste manier in een rimpeloppervlak te wikkelen. Dus bleef ik zoeken naar andere oplossingen waarvoor de DOM niet hoefde te worden gewijzigd.

Radiale verlopen

Met de syntaxis van het radiaal verloop kan ik zowel het midden als de grootte van het verloop regelen. Natuurlijk kan ik hiermee ook de kleur van het verloop regelen, inclusief semi-transparante kleuren. En het loopt nooit over het element waarop het is toegepast. Dus het lijkt erop dat het al alles doet wat ik nodig heb!

Niet zo snel ... er ontbreekt één ding: de eigenschap background-image is niet animeerbaar. Ik kon het verloop niet laten groeien en vervagen tot transparant met behulp van CSS-animaties. Het is me gelukt om het te laten groeien door de eigenschap op achtergrondgrootte te animeren, maar dat was alles wat ik kon doen.

Ik heb een paar andere dingen geprobeerd, zoals het hebben van een vervagende cirkel als een geanimeerde afbeelding (met het apng-formaat), en heb het als achtergrondafbeelding toegepast. Maar toen kon ik niet bepalen wanneer de beeldlus begon en eindigde.

Eindelijk een oplossing met JavaScript

Wat u niet kunt doen in CSS, kunt u doen in JavaScript. Na meer tijd te hebben doorgebracht dan ik wil toegeven dat ik probeer dit effect te laten werken met CSS-animaties, gaf ik het op en besloot ik de animatie in JavaScript te schrijven.

Ik begon met de bovenstaande oplossing met radiaal verloop en gebruikte window.requestAnimationFrame om een ​​vloeiende animatie te maken van het radiale verloop, groeiend en vervagen. Hier is mijn laatste oplossing:

Gevolgtrekking

Het is dus mogelijk om rimpeleffecten op verzendknoppen te hebben, alleen niet met CSS alleen.

Ik kon deze techniek nergens op internet vinden, dus ik noem hem de mijne. De rimpeltechniek van Leonardo vereist geen wijzigingen in DOM en werkt voor elk element omdat het niet afhankelijk is van pseudo-elementen of onderliggende elementen. Het is echter geen foutloze oplossing.

Ten eerste is er de prestatie. Door het verloop met JavaScript te animeren, verliest u veel browseroptimalisaties. Maar omdat de enige eigenschap die wordt gewijzigd, de achtergrondafbeelding is, vermoed ik dat browsers niet opnieuw hoeven te plaatsen en alleen de stijlen opnieuw moeten toepassen en het element opnieuw moeten schilderen. In de praktijk is dat precies wat er gebeurt en de prestaties zijn echt goed. De uitzondering op die verklaring is Firefox Mobile, die om een ​​of andere reden de animatie niet bijhoudt. (bewerken: animatie verloopt soepel op moderne Firefox Mobile-versies)

Ten tweede gebruikt de techniek de eigenschap background-image van de knop. Als uw ontwerp vereist dat op uw knoppen een afbeelding op de achtergrond wordt toegepast, zou het rimpeleffect dat teniet doen. Als je die afbeelding echt nodig hebt in je ontwerp, dan kan JavaScript worden aangepast om het radiale verloop bovenop de bestaande achtergrondafbeelding te tekenen.

Ten derde lijkt dit niet te werken in Internet Explorer. Ik zie echter geen enkele reden waarom het niet zou moeten werken met IE10 en hoger. Misschien komt het omdat IE een andere syntaxis gebruikt voor radiaal verloop. Maar wie geeft er tegenwoordig om IE? (bewerken: deze methode werkt zonder problemen op Internet Explorer 11)