Eenvoudige Veeg Met Vanille JavaScript

0
64

Ik gebruikte om te denken dat de uitvoering van swipe-bewegingen moest heel moeilijk, maar ik heb onlangs vond ik mezelf in een situatie waar ik het moest doen en ontdekt de realiteit is nergens in de buurt zo somber als ik me had voorgesteld.

Dit artikel gaat om je, stap voor stap, door middel van de uitvoering met de minste hoeveelheid van code die ik kon verzinnen. Dus, laten we meteen aan de slag!

De HTML-Structuur

We beginnen met een .container heeft een heleboel afbeeldingen in:

<div class= “container”>
<img src=’img1.jpg’ alt=’image description’/>

</div>

Basic Stijlen

Wij maken gebruik van display: flex ervoor zorgen dat beelden naast elkaar en geen spaties in tussen. lijn-items: midden midden uitgelijnd verticaal. We maken zowel de beelden en de container neemt de breedte van de container de ouder (het lichaam in ons geval).

.container {
display: flex;
lijn-items: center;
breedte: 100%;

img {
min-width: 100%; /* nodig om Firefox niet img passend */
breedte: 100%; /* kan het niet uit als het breekt Chrome */
}
}

Het feit dat zowel de .container en de onderliggende afbeeldingen hebben dezelfde breedte maakt deze beelden morsen op de rechterkant (gemarkeerd door de rode contour) het creëren van een horizontale scrollbar, maar dit is precies wat we willen:

De oorspronkelijke lay-out (zie demo).

Gezien het feit dat niet alle afbeeldingen hebben dezelfde afmetingen en aspect ratio, hebben we een beetje witruimte boven en onder een aantal van hen. Dus, we gaan de bekleding, die door het geven van de .container een expliciete hoogte die moet vrij veel werk voor de gemiddelde verhouding van deze foto ‘ s en het instellen van overflow-y om de verborgen:

.container {
/* hetzelfde als voorheen */
overflow-y: hidden;
hoogte: 50vw;
max-height: 100vh;
}

Het resultaat is hieronder te zien, met alle afbeeldingen worden bijgesneden tot dezelfde hoogte en geen lege plekken meer:

Het resultaat na de beelden worden bijgesneden door overflow-y op .container (zie demo).

Oke, maar nu hebben we een horizontale scrollbar .de container zelf. Nou, dat is eigenlijk een goede zaak voor de geen JavaScript geval.

Anders creëren we een CSS-variabele-n voor het aantal beelden en we gebruiken deze om te maken .container breed genoeg is om al haar imago kinderen die hebben nog steeds dezelfde breedte als de ouder (het lichaam in dit geval):

.container {
–n: 1;
breedte: 100%;
breedte: calc(var (- n)*100%);

img {
min-width: 100%;
breedte: 100%;
breedte: calc(100%/var(–n));
}
}

Merk op dat we houden van de vorige breedte declaraties van uitwijkmogelijkheden. De calc () – waarden veranderen niet van een ding tot we –n van de JavaScript-na het krijgen van ons .container en het aantal beelden van kinderen geldt:

const _C = document.querySelector(‘.container’),
N = _C.kinderen.lengte;

_C.stijl.setProperty (de’ – n’, N)

Nu is het onze .container is uitgebreid om alle afbeeldingen in:

Lay-out met extra container (live demo).

Schakelen Beelden

Vervolgens krijgen we te ontdoen van de horizontale schuifbalk door het instellen van overflow-x: hidden op onze container de ouder (het lichaam in ons geval) en we maken een ander CSS-variabele die in het bezit van de index van de momenteel geselecteerde afbeelding (–i). Wij gebruiken deze naar de juiste positie .container met betrekking tot de viewport via een vertaling (vergeet niet dat % waarden te vertalen in() functies zijn in vergelijking met de afmetingen van het element dat we hebben deze transformatie op):

body { overflow-x: hidden }

.container {
/* stijlen als voorheen */
transformeren: translate(calc(var(–i, 0)/var (- n)*-100%));
}

Het veranderen van de –ik naar een ander geheel getal groter of gelijk aan nul, maar kleiner dan –n, brengt een ander beeld in beeld, zoals wordt geïllustreerd door de interactieve demo hieronder (de waarde van –ik wordt gecontroleerd door een bereik input):

Zie de Pen door thebabydino (@thebabydino) op CodePen.

Goed, maar we willen het niet gebruiken van een schuifbalk om dit te doen.

Het idee is dat we gaan voor het detecteren van de richting van de beweging tussen de “touchstart” (of “mousedown”) evenement en de “touchend” (of “mouseup”) en vervolgens de update –ik dienovereenkomstig te verplaatsen van de container zodanig dat het volgende beeld (als er een is) in de gewenste richting beweegt in de viewport.

function lock(e) {};

functie verplaatsen(e) {};

_C.addEventListener(‘mousedown’, lock, false);
_C.addEventListener(‘touchstart’, lock, false);

_C.addEventListener(‘mouseup’, verplaatsen, false);
_C.addEventListener(‘touchend’, verplaatsen, false);

Merk op dat dit alleen werkt voor de muis als de aanwijzer-evenementen: geen op de afbeeldingen.

.container {
/* stijlen als voorheen */

img {
/* stijlen als voorheen */
pointer-evenementen: none;
}
}

Ook, Edge moet hebben touch events ingeschakeld van over:vlaggen als deze optie is standaard uitgeschakeld):

Waardoor raak evenementen in de Rand.

Voordat we vullen de lock() en move() functies, wij verenigen de touch en klik gevallen:

functie unify(e) { return e.changedTouches ? e.changedTouches[0] : e };

Vergrendeling op “touchstart” (of “mousedown”) verkrijgen en opslaan van de x-coördinaat in een eerste coördinaat variabele x0:

laat x0 = null;

function lock(e) { x0 = verenigen(e).clientX };

Om te zien hoe te verplaatsen .container (of als we doen dat omdat we niet willen om verder te gaan wanneer we aan het einde), controleren we of wij hebben het vergrendelen() actie, en als we die hebben, lezen we de actuele x-coördinaat berekenen het verschil tussen x0 en op te lossen wat te doen van het teken en de huidige index:

laat i = 0;

functie verplaatsen(e) {
als(x0 || x0 === 0) {
laat dx = verenigen(e).clientX – x0, s = Wiskunde.teken(dx);

if (i > 0 || s < 0) && (i < N – 1 || s > 0))
_C.stijl.setProperty(‘–i’, i -= s);

x0 = null
}
};

Het resultaat op te slepen naar links/ rechts is hieronder te zien:

Het schakelen tussen beelden op veeg (live demo). Pogingen om naar rechts te schuiven op de eerste afbeelding of links op de laatste niets doen als we geen andere afbeelding voor of na, respectievelijk.

Het bovenstaande is het verwachte resultaat en het resultaat dat we krijgen in Chrome voor een beetje slepen en Firefox. Echter, Edge gaat achteruit en vooruit wanneer we sleep naar links of rechts, dat is iets dat Chrome ook doet op een beetje meer te slepen.

De rand van het navigeren in de paginaweergave naar voren of naar achteren links of rechts te vegen.

Om dit op te heffen, moeten we een “touchmove” event-listener:

_C.addEventListener(‘touchmove’, e => {e.preventDefault()}, false)

Oke, we hebben nu iets werkt in alle browsers, maar het lijkt niet op wat we echt na… nog!

Vloeiende Beweging

De makkelijkste manier om te bewegen in de richting van het krijgen wat we willen, is door het toevoegen van een overgang:

.container {
/* stijlen als voorheen */
overgang: de transformatie .5s gemak-outl
}

En hier is het, een heel eenvoudige veeg-effect in ongeveer 25 lijnen van JavaScript en ongeveer 25 regels van CSS:

Werken veeg-effect (live demo).

Helaas, er is een Edge-bug dat maakt een overgang naar een CSS-variabele-afhankelijk calc() vertaling mislukken. Ugh, ik denk dat we hebben om te vergeten over de Rand voor nu.

Het verfijnen van de Hele Zaak

Met alle coole veeg effecten die er zijn, wat hebben we tot nu toe niet goed gesneden, dus laten we zien welke verbeteringen kunnen worden aangebracht.

Betere Visuele Cues Tijdens Het Slepen

Ten eerste, er gebeurt niets, terwijl we slepen, alle actie volgt de “touchend” (of “mouseup”) evenement. Dus, terwijl we slepen, we hebben geen indicatie van wat er nu gaat gebeuren. Is er een volgende foto te schakelen om in de gewenste richting? Of zijn we aan het einde gekomen van de lijn en zal er niets gebeuren?

Om te zorgen dat we passen de vertaling bedrag een beetje door het toevoegen van een CSS-variabele tx –dat is oorspronkelijk 0px:

transformeren: translate(calc(var(–i, 0)/var (- n)*-100% + var(–tx, 0px)))

We maken gebruik van twee event-listeners: één voor “touchmove” en een voor “mousemove”. Merk op dat we reeds het voorkomen van achteren en naar voren navigatie in Chrome met behulp van de “touchmove” luisteraar:

functie slepen(e) { e.preventDefault() };

_C.addEventListener(‘mousemove’, sleep, false);
_C.addEventListener(‘touchmove’, sleep, false);

Laten we nu het vullen van de sleep() functie! Als we het hebben uitgevoerd van het slot() actie, lezen we het actuele x-coördinaat berekenen van het verschil dx tussen deze coördineren en de oorspronkelijke x0 en stel tx –om deze waarde (wat is een pixel waarde).

functie slepen(e) {
e.preventDefault();

als(x0 || x0 === 0)
_C.stijl.setProperty(‘–tx”, `${Math.ronde(unify(e).clientX – x0)}px`)
};

We moeten er ook voor zorgen reset tx –te 0px aan het einde en verwijder de overgang voor de duur van de sleep. Om dit gemakkelijker te maken, we gaan de overgang verklaring op .gladde klasse:

.gladde { transition: transformeren .5s gemak-out; }

In het slot() functie is, verwijderen we deze klasse van de .container van het (wij zullen het toevoegen aan het einde op “touchend” en “mouseup”) en ook een vergrendeld boolean variabele, dus we hoeven niet te blijven uitvoeren van de x0 || x0 === 0 controleren. Vervolgens gebruiken We de vergrendelde variabele voor de controles in de plaats:

laat locked = false;

function lock(e) {
x0 = verenigen(e).clientX;
_C.classList.toggle(‘smooth’, !(locked = true))
};

functie slepen(e) {
e.preventDefault();
als(vergrendeld) { /* hetzelfde als voorheen */ }
};

functie verplaatsen(e) {
als(vergrendeld) {
laat dx = verenigen(e).clientX – x0, s = Wiskunde.teken(dx);

if (i > 0 || s < 0) && (i < N – 1 || s > 0))
_C.stijl.setProperty(‘–i’, i -= s);
_C.stijl.setProperty(‘–tx”, ‘0px’);
_C.classList.toggle(‘smooth’, !(locked = false));
x0 = null
}
};

Het resultaat is hieronder te zien. Terwijl we nog steeds te slepen, we hebben nu een visuele indicatie van wat er gaat gebeuren volgende:

Veeg met een visuele cues tijdens het slepen (live demo).

Fix de overgang-duur

Op dit punt, zijn we altijd met dezelfde overgang-duur geen kwestie hoeveel van een beeld van de breedte die we nog hebben te vertalen na het slepen. We kunnen vaststellen dat in een vrij eenvoudige wijze door de invoering van een factor f die we ook ingesteld als een CSS-variabele om ons te helpen bij het berekenen van de werkelijke duur van de animatie:

.gladde { transition: de transformatie van calc(var(–f, 1)*.5s) ease-out; }

In de JavaScript, krijgen we een beeld van de breedte (bijgewerkt op “resize”) en berekenen voor welk deel van dit we hebben gesleept horizontaal:

laat w;

functie omvang() { w = venster.innerWidth };

functie verplaatsen(e) {
als(vergrendeld) {
laat dx = verenigen(e).clientX – x0, s = Wiskunde.teken(dx),
f = +(s*dx/w).toFixed(2);

if (i > 0 || s < 0) && (i < N – 1 || s > 0)) {
_C.stijl.setProperty(‘–i’, i -= s);
f = 1 – f
}

_C.stijl.setProperty(‘–tx”, ‘0px’);
_C.stijl.setProperty(‘–f’, f);
_C.classList.toggle(‘smooth’, !(locked = false));
x0 = null
}
};

omvang();

addEventListener(‘resize’, grootte, false);

Dit nu geeft ons een beter resultaat.

Ga terug als onvoldoende sleep

Laten we zeggen dat we niet willen om verder te gaan naar de volgende afbeelding als we alleen sleep een beetje onder een bepaalde drempel. Want nu, een 1px verschil tijdens het slepen betekent dat we vooraf naar de volgende afbeelding en dat voelt een beetje onnatuurlijk aan.

Om dit op te lossen, stellen we een drempel op laten we zeggen 20% van een afbeelding breedte:

functie verplaatsen(e) {
als(vergrendeld) {
laat dx = verenigen(e).clientX – x0, s = Wiskunde.teken(dx),
f = +(s*dx/w).toFixed(2);

if (i > 0 || s < 0) && (i < N – 1 || s > 0) && f > .2) {
/* hetzelfde als voorheen */
}

/* hetzelfde als voorheen */
}
};

Het resultaat is hieronder te zien:

We hebben alleen te gaan naar de volgende afbeelding als we slepen genoeg (live demo).

Misschien een Bounce?

Dit is iets dat ik niet zeker weet is het een goed idee, maar ik te popelen om het toch te proberen: verander de functie van de timing, zodat we introduceren een bounce. Na een beetje van het slepen van de handgrepen op cubic-bezier.com ik kwam met een resultaat dat leek veelbelovend:

Wat ons gekozen cubic Bézier-de functie van de timing lijkt in vergelijking met een gewone gemak-out.

overgang: de transformatie van calc(var(–f)*.5s) cubic-bezier(1, 1.59, .61, .74);

Met behulp van een aangepaste CSS timing functie om een bounce (live demo).

Hoe zit het met de JavaScript Manier Dan?

We konden het realiseren van een betere mate van controle over een natuurlijker gevoel en meer complexe stuitert door het nemen van de JavaScript-route voor de overgang. Dit zou ook geef ons Edge ondersteuning.

We beginnen met het wegwerken van de overgang en de tx –en –f CSS variabelen. Dit vermindert onze transformeren naar wat het oorspronkelijk was:

transformeren: translate(calc(var(–i, 0)/var (- n)*-100%));

De bovenstaande code betekent ook –ik zal niet per se een geheel getal meer. Blijft het een geheel getal is, terwijl wij één beeld volledig in beeld, dat is niet meer het geval, terwijl we slepen of tijdens de beweging na het activeren van de “touchend” of “mouseup” gebeurtenissen.

Bijvoorbeeld, terwijl wij de eerste afbeelding volledig te bekijken, –i is 0. Terwijl wij de tweede, volledig in beeld, –ik is 1. Als we halverwege tussen de eerste en de tweede, –ik is .5. Als we een kwart van de eerste drie kwartalen van het tweede beeld, –ik is .75.

We werken dan de JavaScript-voor het vervangen van de code onderdelen waar we het bijwerken van deze CSS-variabelen. Ten eerste, wij verzorgen het slot() functie, waar we greppel heen en weer schakelen .gladde klasse en van de sleep() functie, of vervangen we de actualisering van de tx –variabele hebben we gedumpt met het bijwerken –ik, die, zoals eerder vermeld, hoeft niet te worden een geheel getal meer:

function lock(e) {
x0 = verenigen(e).clientX;
locked = true
};

functie slepen(e) {
e.preventDefault();

als(vergrendeld) {
laat dx = verenigen(e).clientX – x0,
f = +(dx/w).toFixed(2);

_C.stijl.setProperty(‘–i’, i – f)
}
};

Voordat we ook een update van de move() functie, introduceren we twee nieuwe variabelen, ini en fin. Deze vertegenwoordigen de initiële waarde die we stellen –ik aan het begin van de animatie en de uiteindelijke waarde stellen we dezelfde variabele op het einde van de animatie. Ook hebben We een animatie maken van de functie ani():

laat ini-fin;

functie ani() {};

functie verplaatsen(e) {
als(vergrendeld) {
laat dx = verenigen(e).clientX – x0,
s = Wiskunde.teken(dx),
f = +(s*dx/w).toFixed(2);

ini = i – s*f;

if (i > 0 || s < 0) && (i < N – 1 || s > 0) && f > .2) {
i -= s;
f = 1 – f
}

fin = i;
esther();
x0 = null;
locked = false;
}
};

Is dit niet teveel afwijkt van de code die we eerst hadden. Wat veranderd is, is dat we het niet instellen van een CSS-variabelen in deze functie meer, maar in plaats daarvan wordt ingesteld in het ini en de fin JavaScript variabelen en de animatie ani() functie.

ini is de initiële waarde die wij stellen –ik tot aan het begin van de animatie die de “touchend”/ “mouseup” event triggers. Dit wordt bepaald door de huidige positie hebben we als één van deze twee evenementen branden.

fin is de uiteindelijke waarde die wij stellen –ik aan het eind van dezelfde animatie. Dit is altijd een geheel getal, omdat we altijd eindigen met een afbeelding volledig in het zicht, dus fin en –ik de index van dat beeld. Dit is de volgende afbeelding in de gewenste richting als we gesleept genoeg (f > .2) en als er een volgende afbeelding in de gewenste richting ((i > 0 || s < 0) && (i < N – 1 || s > 0)). In dit geval hebben we ook een update van de JavaScript-variabele opslaan van de huidige image index (i) en de relatieve afstand tot het (f). Anders, het is dezelfde afbeelding, zodat ik en f hoeft niet te worden bijgewerkt.

Nu, laten we verder gaan naar de ani() functie. We beginnen met een vereenvoudigde lineaire versie die vertrekt uit een verandering van richting.

const NF = 30;

laat rID = null;

functie stopAni() {
cancelAnimationFrame(rID);
rID = null
};

functie ani(cf = 0) {
_C.stijl.setProperty(‘–i’, ini + (fin – ini)*cf/NF);

als(cf === NF) {
stopAni();
terug
}

rID = requestAnimationFrame(ani.binden (++cf))
};

De voornaamste bedoeling hier is dat de overgang tussen de initiële waarde ini en de laatste fin gebeurt over een totaal aantal van frames NF. Elke keer als we bellen met de ani() functie, berekenen we de voortgang als de verhouding tussen het huidige frame-index cf en het totaal aantal frames NF. Dit is altijd een getal tussen 0 en 1 (of je kan het als een percentage, gaande van 0% tot 100%). Vervolgens gebruiken We deze vooruitgang waarde te krijgen van de huidige waarde van –ik en zet het in de style attribuut van onze container _C. Als we naar de finale staat (het huidige frame-index cf is gelijk aan het totaal aantal frames NF, we verlaten de animatie loop). Anders gaan we gewoon verhogen van het huidige frame-index cf en gesprek ani() weer.

Op dit moment hebben we een werkende demo met een lineaire JavaScript overgang:

Versie met lineaire JavaScript overgang (live demo).

Dit heeft echter het probleem dat we in eerste instantie had in de CSS geval: ongeacht de afstand, we hebben om vlot vertalen in ons element dan op de release (“touchend” / “mouseup”) en de duur is altijd hetzelfde omdat we altijd animeren over hetzelfde aantal frames NF.

Laten we vaststellen dat!

Om dit te kunnen doen, introduceren we een andere variabele anf waar we slaan het effectieve aantal beelden die we gebruiken en waarvan de waarde berekenen we in de move() functie aanroepen voordat de animatie functie ani():

functie verplaatsen(e) {
als(vergrendeld) {
laat dx = verenigen(e).clientX – x0,
s = Wiskunde.teken(dx),
f = +(s*dx/w).toFixed(2);

/* hetzelfde als voorheen */

anf = Wiskunde.ronde(f*NF);
esther();

/* hetzelfde als voorheen */
}
};

We moeten ook vervangen NF met anf in de animatie functie ani():

functie ani(cf = 0) {
_C.stijl.setProperty(‘–i’, ini + (fin – ini)*cf/anf);

als(cf === anf) { /* hetzelfde als voorheen */ }

/* hetzelfde als voorheen */
};

Met deze, we hebben vast de kwestie van timing!

Versie met lineaire JavaScript overgang bij constante snelheid (live demo).

Oke, maar een lineaire timing functie is niet al te spannend.

We kunnen proberen de JavaScript-equivalenten van CSS timing functies zoals ease-in, ease-out of ease-in-uit en zie hoe ze elkaar vergelijken. Ik heb al uitgelegd in detail hoe je deze in de eerder gelinkte artikel, dus ik ben niet van plan om te gaan door weer en gewoon laten vallen van het object met alle van hen in de code:

const TFN = {
‘lineaire’: function(k) { return k },
‘gemak-in’: function(k, e = 1.675) {
terug Math.pow(k, e)
},
het ‘gemak’: function(k, e = 1.675) {
return 1 – Wiskunde.pow(1 – k, e)
},
‘gemak-in-out’ – functie(k) {
terug .5*(Math.sin((k) – .5)*Wiskunde.PI) + 1)
}
};

De k-waarde is de vooruitgang, dat is de verhouding tussen het huidige frame-index cf en het effectieve aantal beelden dat de overgang gebeurt er dan anf. Dit betekent dat we wijzigen de ani() functie een beetje als we willen gebruik maken van het gemak-out optie voor het voorbeeld:

functie ani(cf = 0) {
_C.stijl.setProperty(‘–i’, ini + (fin – ini)*TFN[‘ease-out’](cf/anf));

/* hetzelfde als voorheen */
};

Versie met gemak-out JavaScript overgang (live demo).

We kunnen ook dingen meer interessant door het gebruik van de soort van het stuiteren van de functie van de timing die CSS niet ons geven. Bijvoorbeeld iets als een geïllustreerd door de demo hieronder (klik om te leiden tot een overgang):

Zie de Pen door thebabydino (@thebabydino) op CodePen.

De grafische dit zou zijn enigszins vergelijkbaar met die van de easeOutBounce de functie van de timing van easings.net.

Grafische weergave van de timing functie.

Het proces voor het krijgen van deze vorm van timing functie is vergelijkbaar met dat voor het verkrijgen van de JavaScript versie van de CSS-gemak-in-weer, zoals beschreven in het eerder gelinkte artikel over het emuleren van CSS timing functies met JavaScript).

We beginnen met de cosinus-functie op [0, 90°] interval (of op [0, π/2] in radialen) voor geen bounce, [0, 270°] ([0, 3·π/2]) voor 1 stuiteren, [0, 450°] ([0, 5·π/2]) voor 2 springkussens en nog veel meer… in het algemeen is de [0, (n + ½)·180°] interval[0, (n + ½)·π]) voor n stuitert.

Zie de Pen door thebabydino (@thebabydino) op CodePen.

De ingang van dit cos(k) functie is in de [0, 450°] interval, terwijl de output is in de [-1, 1] interval. Maar wat wij willen is een functie waarvan het domein is de [0, 1] – interval en waarvan de codomain is ook de [0, 1] interval.

We beperken de codomain aan de [0, 1] interval door alleen het nemen van de absolute waarde |cos(k)|:

Zie de Pen door thebabydino (@thebabydino) op CodePen.

Terwijl we het interval we wilden voor de codomain, we willen de waarde van deze functie op 0 gelijk is aan 0 en de waarde op het andere einde van het interval 1). Momenteel, het is de andere manier rond, maar we kunnen dit oplossen als we de functie van 1 |cos(k)|:

Zie de Pen door thebabydino (@thebabydino) op CodePen.

Nu kunnen we overgaan tot het beperken van het domein [0, (n + ½)·180°] interval [0, 1] interval. Om dit te doen, veranderen we onze functie 1 |cos(k)·(n + ½)·180°)|:

Zie de Pen door thebabydino (@thebabydino) op CodePen.

Dit geeft ons de gewenste domeinnaam en codomain, maar we hebben nog steeds een aantal problemen.

Eerste van alles, al onze springkussens hebben dezelfde hoogte, maar we willen op de hoogte te dalen als k toeneemt van 0 tot 1. Onze oplossing in dit geval is te vermenigvuldigen met de cosinus met 1 – k (of met een vermogen van 1 – k voor een niet-lineaire afname in amplitude). De interactieve demo hieronder laat zien hoe dit amplitude veranderingen op de verschillende exponenten a en welke invloed dit heeft op de functie die we tot nu toe:

Zie de Pen door thebabydino (@thebabydino) op CodePen.

In de tweede plaats van de bounces nemen dezelfde hoeveelheid tijd, ook al is hun amplitudes blijven verlagen. Het eerste idee hier is om gebruik te maken van een vermogen van k in de cosinus-functie in plaats van gewoon k. Deze beheert om dingen raar als de cosinus niet raakt 0 op gelijke intervallen meer, wat betekent dat we niet altijd krijgen dat f(1) = 1 meer en dat is wat we willen altijd behoefte van de functie van de timing we daadwerkelijk gaat gebruiken. Echter, voor iets als a = 2.75, n = 3 en b = – 1.5, krijgen we een resultaat bevredigend, dus we laten het op dat, hoewel het kan aangepast worden voor een betere controle:

De timing van de functie die we willen uitproberen.

Dit is de functie die we proberen in de JavaScript-als we dat willen sommige stuiteren gebeuren.

const TFN = {
/* de andere functie die we hadden voordat */
‘bounce-out’: function(k), n = 3, a = 2.75, b = 1.5) {
return 1 – Wiskunde.pow(1 – k, a)*Wiskunde.abs(Math.cos(Math.pow(k, b)*(n + .5)*Wiskunde.PI))
}
};

Hmm, lijkt een beetje te extreem in de praktijk:

Versie met een stuiterende JavaScript overgang (live demo).

Misschien kunnen we n is afhankelijk van de hoogte van de vertaling die we nog nodig hebben voor het uitvoeren van het moment van de release. We maken het op in een variabele, die we vervolgens in de move() functie aanroepen voordat de animatie functie ani():

const TFN = {
/* de andere functie die we hadden voordat */
‘bounce-out’: function(k, a = 2.75, b = 1.5) {
return 1 – Wiskunde.pow(1 – k, a)*Wiskunde.abs(Math.cos(Math.pow(k, b)*(n + .5)*Wiskunde.PI))
}
};

var n;

functie verplaatsen(e) {
als(vergrendeld) {
laat dx = verenigen(e).clientX – x0,
s = Wiskunde.teken(dx),
f = +(s*dx/w).toFixed(2);

/* hetzelfde als voorheen */

n = 2 + Wiskunde.ronde(f)
esther();
/* hetzelfde als voorheen */
}
};

Dit geeft ons onze uiteindelijke resultaat:

Versie met de laatste stuiteren JavaScript overgang (live demo).

Er is zeker nog ruimte voor verbetering, maar ik heb een gevoel voor wat een goede animatie, dus zal ik het bij laten. Zoals het is, dit is nu functioneel cross-browser (zonder enige van de Rand van de problemen die de versie met behulp van een CSS-overgang) en redelijk flexibel.