Dans la première partie de la série introductive Popmotion, nous avons appris à utiliser basé sur le temps des animations comme interpolation
et images clés
. Nous avons également appris à utiliser ces animations sur le DOM en utilisant le logiciel performant. styler
.
Dans la deuxième partie, nous avons appris à utiliser aiguille
suivi et enregistrement rapidité
. Nous avons ensuite utilisé cela pour alimenter le basé sur la vitesse des animations printemps
, pourriture
, et la physique
.
Dans cette dernière partie, nous allons créer un widget de nettoyage, et nous allons l’utiliser pour nettoyer un images clés
animation. Nous allons faire le widget lui-même à partir d'une combinaison de suivi de pointeur, ainsi que printemps
et pourriture
pour lui donner une sensation plus viscérale que les laveurs ordinaires.
Essayez vous-même:
Commencez par créer ce CodePen pour le modèle HTML. Comme auparavant, comme il s'agit d'un tutoriel intermédiaire, je ne vais pas tout passer en revue..
La principale chose à noter est que la poignée de l’autolaveuse est composée de deux div
éléments: .manipuler
et .zone de frappe
.
.manipuler
est l’indicateur visuel rond et bleu de l’emplacement de la poignée de l’épurateur. Nous l'avons intégré à un élément invisible de la zone d'accès afin de faciliter la capture de l'élément aux utilisateurs d'écran tactile..
En haut de votre panneau JS, importez tout ce que nous allons utiliser dans ce tutoriel:
const assouplissement, images clés, pointeur, décroissance, ressort, styler, transformer, écouter, valeur = popmotion; const pipe, clamp, conditionnel, linearSpring, interpolate = transformer;
Nous allons avoir besoin de trois éléments dans ce tutoriel. Nous animerons le .boîte
, faites glisser et animer le .zone de frappe
, et mesurer le .intervalle
.
Créons aussi styler
s pour les éléments que nous allons animer:
const box = document.querySelector ('. box'); const boxStyler = styler (box); const handle = document.querySelector ('. handle-hit-area'); const handleStyler = styler (handle); const range = document.querySelector ('. range');
Pour notre animation scrubbable, nous allons faire la .boîte
se déplacer de gauche à droite avec images clés
. Cependant, nous pourrions tout aussi facilement frotter un interpolation
ou chronologie
animation utilisant la même méthode que celle décrite plus loin dans ce tutoriel.
const boxAnimation = keyframes (valeurs: [0, -150, 150, 0], easings: [easing.backOut, easing.backOut, easing.easeOut], durée: 2000). start (boxStyler.set ('x' ));
Votre animation va maintenant jouer. Mais nous ne voulons pas ça! Faisons une pause pour le moment:
boxAnimation.pause ();
Il est temps d'utiliser aiguille
faire glisser notre manche de récureur. Dans le tutoriel précédent, nous avons utilisé à la fois X
et y
propriétés, mais avec un laveur nous avons seulement besoin X
.
Nous préférons garder notre code réutilisable et suivre un seul aiguille
L'axe est un cas d'utilisation assez commun. Créons donc une nouvelle fonction appelée avec imagination, pointeurX
.
Cela fonctionnera exactement comme aiguille
sauf que cela ne prendra qu'un seul nombre comme argument et ne produira qu'un seul nombre (X
):
const pointeurX = (x) => pointeur (x). pipe (xy => xy.x);
Ici, vous pouvez voir que nous utilisons une méthode de aiguille
appelé tuyau
. tuyau
est disponible sur toutes les actions Popmotion que nous avons vues jusqu'à présent, y compris images clés
.
tuyau
accepte plusieurs fonctions. Quand l'action est début
toutes les sorties passeront successivement par chacune de ces fonctions, avant la mettre à jour
fonction fournie à début
les feux.
Dans ce cas, notre fonction est simplement:
xy => xy.x
Tout ce qu'il fait est de prendre la x, y
objet généralement produit par aiguille
et en retournant juste le X
axe.
Nous devons savoir si l'utilisateur a commencé à appuyer sur la poignée avant de commencer à suivre avec notre nouveau pointeurX
une fonction.
Dans le dernier tutoriel, nous avons utilisé le traditionnel addEventListener
une fonction. Cette fois, nous allons utiliser une autre fonction Popmotion appelée écoute
. écoute
fournit également un tuyau
méthode, ainsi que l'accès à toutes les méthodes d'action, mais on ne va pas l'utiliser ici.
écoute
nous permet d'ajouter des écouteurs d'événements à plusieurs événements avec une seule fonction, similaire à jQuery. Nous pouvons donc condenser les quatre auditeurs d’événement précédents à deux:
listen (handle, 'mousedown touchstart'). start (startDrag); écouter (document, 'mouseup touchend'). start (stopDrag);
Nous aurons besoin de la poignée de x rapidité
plus tard, alors faisons-en un valeur
, comme nous l’avons appris dans le dernier tutoriel, nous permet d’interroger la vitesse. Sur la ligne après on définit poignéeStyler
, ajouter:
const handleX = valeur (0, handleStyler.set ('x'));
Maintenant, nous pouvons ajouter notre startDrag
et stopDrag
les fonctions:
const startDrag = () => pointeurX (handleX.get ()) .start (handleX); const stopDrag = () => handleX.stop ();
Pour le moment, la poignée peut être nettoyée au-delà des limites du curseur, mais nous y reviendrons plus tard..
Maintenant, nous avons un récureur visuellement fonctionnel, mais nous ne nettoyons pas l'animation proprement dite..
Chaque valeur
a un souscrire
méthode. Cela nous permet d’attacher plusieurs abonnés au feu lorsque le valeur
changements. Nous voulons chercher le images clés
animation chaque fois handleX
mises à jour.
Commencez par mesurer le curseur. Sur la ligne après on définit intervalle
, ajouter:
const rangeWidth = range.getBoundingClientRect (). width;
keyframes.seek
accepte une valeur de progression telle qu'exprimée à partir de 0
à 1
, alors que notre handleX
est défini avec les valeurs de pixel de 0
à rangeWidth
.
Nous pouvons convertir de la mesure de pixel à un 0
à 1
plage en divisant la mesure de pixel actuelle par rangeWidth
. Sur la ligne après boxAnimation.pause ()
, ajoutez cette méthode d'abonnement:
handleX.subscribe (v => boxAnimation.seek (v / rangeWidth));
Maintenant, si vous jouez avec le scrubber, l’animation sera nettoyée avec succès!
La récureuse peut toujours être tirée en dehors des limites de la plage complète. Pour résoudre cela, nous pourrait utilisez simplement un serrer
fonction pour nous assurer de ne pas sortir des valeurs en dehors de 0, étendue de la largeur
.
Au lieu de cela, nous allons faire un pas supplémentaire et attacher des ressorts à la fin de notre curseur. Lorsqu'un utilisateur tire la poignée au-delà de la plage autorisée, il le tirera vers elle. Si l'utilisateur relâche le handle alors qu'il se trouve en dehors de la plage, nous pouvons utiliser un printemps
animation pour le ramener.
Nous ferons de ce processus une fonction unique que nous pourrons fournir au pointeurX
tuyau
méthode. En créant une seule fonction réutilisable, nous pouvons réutiliser ce morceau de code avec n’importe quelle animation Popmotion, avec des plages configurables et des forces de ressorts..
Tout d'abord, appliquons un ressort à la limite la plus à gauche. Nous allons utiliser deux transformateurs, conditionnel
et linearSpring
.
const springRange = (min, max, force) => conditionnel (v => v < min, linearSpring(strength, min) );
conditionnel
prend deux fonctions, une assertion et un transformateur. L'assertion reçoit la valeur fournie et retourne soit vrai
ou faux
. Si cela revient vrai
, la deuxième fonction sera fournie la valeur pour transformer et retourner.
Dans ce cas, l’assertion dit: "Si la valeur fournie est inférieure à min
, passer cette valeur à travers le linearSpring
transformateur. "Le linearSpring
est une fonction de ressort simple qui, contrairement à la la physique
ou printemps
animations, n'a pas de notion de temps. Lui fournir un force
et un cible
, et il va créer une fonction qui "attire" toute valeur donnée vers la cible avec la force définie.
Remplacer notre startDrag
fonctionner avec ceci:
const startDrag = () => pointerX (handleX.get ()) .pipe (springRange (0, rangeWidth, 0.1)) .start (handleX);
Nous passons maintenant le pointeur X
compenser par notre SpringRange
fonction, donc si vous faites glisser la poignée au-delà du côté le plus à gauche, vous remarquerez qu'il tire en arrière.
Appliquer la même chose du côté le plus à droite est une question de composition d'une seconde conditionnel
avec le premier en utilisant le stand-alone tuyau
une fonction:
const springRange = (min, max, résistance) => tuyau (conditionnel (v => v < min, linearSpring(strength, min) ), conditional( v => v> max, linearSpring (force, max)));
Un autre avantage de composer une fonction comme SpringRange
est-ce que cela devient très testable. La fonction qu'il renvoie est, comme tous les transformateurs, une fonction pure qui prend une valeur unique. Vous pouvez tester cette fonction pour voir si elle passe par des valeurs comprises entre min
et max
inaltéré, et s’il applique des ressorts à des valeurs qui se trouvent sans.
Si vous lâchez la poignée alors qu'elle se trouve en dehors de la plage, elle devrait maintenant revenir à sa portée. Pour cela, nous devrons ajuster la stopDrag
fonction pour tirer un printemps
animation:
const stopDrag = () => const x = handleX.get (); (X < 0 || x > rangeWidth)? snapHandleToEnd (x): handleX.stop (); ;
Notre snapHandleToEnd
la fonction ressemble à ceci:
const snapHandleToEnd = (x) => ressort (de: x, vélocité: handleX.getVelocity (), à: x < 0 ? 0 : rangeWidth, damping: 30, stiffness: 5000 ).start(handleX);
Tu peux voir ça à
est défini comme 0
ou rangeWidth
en fonction de quel côté du curseur la poignée se trouve actuellement. En jouant avec amortissement
et rigidité
, vous pouvez jouer avec une gamme de différents ressorts.
J'ai toujours apprécié le nettoyage du lecteur iOS que j'ai toujours apprécié, à savoir que si vous jetiez la poignée, elle ralentirait progressivement au lieu de s'arrêter. Nous pouvons reproduire cela facilement en utilisant le pourriture
animation.
Dans stopDrag
, remplacer handleX.stop ()
avec momentumScroll (x)
.
Ensuite, sur la ligne après le snapHandleToEnd
fonction, ajouter une nouvelle fonction appelée MomentScroll
:
const momentumScroll = (x) => decay (from: x, velocity: handleX.getVelocity ()). start (handleX);
Maintenant, si vous jetez la poignée, elle s’arrêtera progressivement. Il animera également en dehors de la plage du curseur. Nous pouvons arrêter cela en passant le serrer
transformateur à la decay.pipe
méthode:
const momentumScroll = (x) => decay (from: x, velocity: handleX.getVelocity ()). pipe (clamp (0, rangeWidth)) .start (handleX);
En utilisant une combinaison de différentes fonctions Popmotion, nous pouvons créer un laveur qui a un peu plus de vie et d’amusement que la normale.
En utilisant tuyau
, nous composons des fonctions pures simples en comportements plus complexes tout en laissant les pièces composites testables et réutilisables.
Pourquoi ne pas essayer ces défis: