Καλώς ήλθατε στη δεύτερη δόση της σειράς Framer tutorial. Στο τελευταίο άρθρο , μάθαμε για τα βασικά στοιχεία της χρήσης του Framer σε λειτουργία σχεδίασης, καθώς και πώς να γράψουμε έναν απλό κώδικα για να ζωντανεύουν τα σχέδιά μας. Σε αυτό το κομμάτι, θα επικεντρωθούμε στη χρήση του Framer για τη δημιουργία μικρο-αλληλεπιδράσεων και κινούμενων μεταβάσεων. Θα εξετάσουμε πώς να δημιουργήσουμε επτά χρήσιμες αλληλεπιδράσεις για τα πρωτότυπα σας.
Η ομαλή κίνηση, οι αλλαγές κατάστασης και οι λεπτές μεταβάσεις βοηθούν τον χρήστη να κατανοήσει πώς να χρησιμοποιεί τη διεπαφή σας, δίνοντάς του σχόλια για συγκεκριμένες ενέργειες. Συχνά, αυτές οι μεταβάσεις θα αντηχούν ανάλογα του πραγματικού κόσμου (όπως η ολίσθηση ενός διακόπτη διακόπτη) ή θα χρησιμοποιούν κοινά μοτίβα αλληλεπίδρασης συσκευής (όπως πατήστε για επέκταση). Σε αυτό το σεμινάριο, θα επικεντρωθούμε σε αλληλεπιδράσεις που προσθέτουν μια τελική πινελιά στη διεπαφή για να καθοδηγήσουν την κατανόηση και να προκαλέσουν απόλαυση στον χρήστη.
Ρίξτε μια ματιά στα παρακάτω παραδείγματα. Οι σχεδιαστές σε όλο τον κόσμο δημιουργούν αυτές τις μικρο αλληλεπιδράσεις σε διάφορα προϊόντα.
Σε αυτό το σεμινάριο, θα σας δώσω μια επισκόπηση κάθε μικρο-αλληλεπίδρασης και ορισμένων αποσπασμάτων κώδικα. Θα χρησιμοποιήσουμε πολλές διαφορετικές τεχνικές, ώστε να μπορείτε να επιλέξετε αυτή που ταιριάζει καλύτερα στο προϊόν σας. Δεν υπάρχει 'σωστός' τρόπος για να δημιουργήσετε οτιδήποτε μέσα στο Framer Studio - όπως ανέφερα στο προηγούμενο άρθρο μου, το Framer σας δίνει μεγάλη ελευθερία να δημιουργήσετε τον τρόπο που θέλετε.
Έχετε δει αλληλεπιδράσεις όπως αυτές στο παρελθόν; Σίγουρα, έχετε! Τα βλέπετε καθημερινά στο smartphone σας. Ήρθε η ώρα να δημιουργήσετε το δικό σας.
Το κουμπί δράσης αντιπροσωπεύει συχνά την κύρια ενέργεια της τρέχουσας οθόνης. Μερικές φορές περιέχει αρκετές ενέργειες μέσα. Θα δημιουργήσουμε μια αλληλεπίδραση για τη δεύτερη περίπτωση. Κατεβάστε το πρωτότυπο εργασίας εδώ: https://framer.cloud/ShBnH
Για να ξεκινήσετε, δημιουργήστε ένα κύριο κουμπί σε σχήμα κύκλου με ένα εικονίδιο μέσα και δύο μικρότερα κουμπιά τοποθετημένα κάτω από το κύριο κουμπί. Μην ξεχάσετε να επισημάνετε όλα αυτά τα επίπεδα ως διαδραστικά στη λειτουργία σχεδίασης (με την ένδειξη στόχου).
Δημιουργήστε δύο διαφορετικές καταστάσεις για τα επίπεδα. Χρησιμοποιήστε τον παρακάτω κωδικό για να κάνετε τα μικρότερα κουμπιά να κινούνται πάνω από το κύριο και να περιστρέψετε το εικονίδιο 45 °:
button_1.states.a = y: 427 x: 246 width: 64 height: 64 button_2.states.a = y: 330 x: 246 width: 64 height: 64 icon.states.a = rotation: 45
Για να κάνουμε αυτό το πρωτότυπο κινούμενο, πρέπει να προσθέσουμε ένα συμβάν. Αφού πατήσετε το κουμπί ενέργειας, αλλάξτε τις καταστάσεις όλων των επιπέδων:
button.onTap -> button_1.stateCycle() button_2.stateCycle() icon.stateCycle()
Σε αυτό το σημείο, το κινούμενο σχέδιο φαίνεται πολύ μηχανικό. Για να προσθέσετε μια ανθρώπινη πινελιά, θα προσθέσουμε σε μια άνοιξη animation για όλα τα επίπεδα:
button_1.animationOptions = curve: Spring(tension: 170, friction: 12) button_2.animationOptions = delay: 0.05 curve: Spring(tension: 170, friction: 12) icon.animationOptions = curve: Spring(tension: 250, friction: 5)
Το κουμπί δράσης είναι έτοιμο!
Τα παρακάτω βήματα θα σας επιτρέψουν να δημιουργήσετε τη δική σας αλληλεπίδραση διακόπτη. Κατεβάστε το πρωτότυπο εργασίας εδώ: https://framer.cloud/ieypV
Θα χρειαστείτε μόνο δύο πράγματα: τον ίδιο τον διακόπτη, ο οποίος περιέχει τουλάχιστον δύο επίπεδα (φόντο και κουκκίδα), και ορισμένα επίπεδα για κίνηση μετά τη χρήση του διακόπτη.
Θυμάστε από το πρώτο άρθρο πώς να σχεδιάσετε καταστάσεις απευθείας στο Framer Studio; Σχεδιάστε τις πολιτείες σας όπως σας αρέσουν ή χρησιμοποιήστε τις ρυθμίσεις μου:
dot.states.a = x: 50 backgroundColor: 'rgba(5,106,161,1)' switch_bg.states.a = backgroundColor: 'rgba(0,136,205,1)' icon.states.a = opacity: 0 circle.states.a = x: 37 y: 183 width: 301 height: 301 circle_1.states.a = x: 20 y: 166 width: 337 height: 337
Για να λειτουργήσει το πρωτότυπο, πρέπει να προσθέσουμε ένα συμβάν στο διακόπτη. Αφού πατήσετε το διακόπτη, θα αλλάξουμε την κατάσταση όλων των επιπέδων:
switch_1.onTap (event, layer) -> dot.stateCycle() switch_bg.stateCycle() circle.stateCycle() circle_1.stateCycle() icon.stateCycle()
Για να κάνετε τα πάντα πιο φυσικά, προσαρμόστε το χρόνο και την καθυστέρηση όλων των καταστάσεων:
dot.animationOptions = time: 0.2 switch_bg.animationOptions = time: 0.2 circle_1.animationOptions = time: 0.5 curve: Spring circle.animationOptions = time: 0.5 delay: 0.05 curve: Spring icon.animationOptions = time: 0.5 curve: Spring
Τώρα το πρωτότυπό μας ολοκληρώθηκε!
Αυτή είναι μια τυπική αλληλεπίδραση για την κατάργηση, αρχειοθέτηση ή αποθήκευση στοιχείων από μια λίστα. Σύρετε προς τα αριστερά ή προς τα δεξιά και ένα στοιχείο θα διαγραφεί. Κατεβάστε το πρωτότυπο εδώ: https://framer.cloud/rzMWP
Μπορείτε να χρησιμοποιήσετε το δικό σας σχέδιο, αν θέλετε. Απλά πρέπει να διατηρήσετε την ίδια δομή των επιπέδων. Όπως μπορείτε να δείτε στην παραπάνω εικόνα, όλα τα στοιχεία της λίστας έχουν ένα κουμπί 'αναίρεση' κάτω από αυτά.
Για να το κρατήσουμε απλό, θα δημιουργήσουμε μια αλληλεπίδραση μόνο για το πρώτο στοιχείο λίστας. Αρχικά, κάντε το στοιχείο λίστας με δυνατότητα μεταφοράς: item.draggable = true
.
Στη συνέχεια κλειδώστε τον κατακόρυφο άξονα: item.draggable.vertical = false
.
Ρυθμίστε τους περιορισμούς της συρόμενης περιοχής: item.draggable.constraints
Και τέλος ορίστε το μέγεθος στο μέγεθος του αντικειμένου: size: item
.
Έτσι φαίνεται ολόκληρος ο κώδικας:
item.draggable = true item.draggable.vertical = false item.draggable.constraints = size: item
Τώρα μπορείτε να σύρετε αριστερά και δεξιά, και το στοιχείο θα επιστρέφει πάντα στην αρχική του θέση.
Στη συνέχεια, δημιουργήστε την κατάσταση για το στοιχείο λίστας όταν καταργηθεί. Απλώς το μετακίνησα έξω από την οθόνη χρησιμοποιώντας τον άξονα x.
item.states.a = x: -360
Τέλος, πρέπει να δημιουργήσουμε μια σκανδάλη για να ξεκινήσουμε την αλληλεπίδραση. Όταν σύρουμε το στοιχείο στην αριστερή πλευρά της οθόνης, θα πρέπει να αφαιρεθεί. Ο κώδικας θα έχει την εξής μορφή:
item.onMove -> if item.x <-70 item.stateCycle('a')
Σε αυτήν την περίπτωση, χρησιμοποιούμε μια δήλωση “if”. Ο παραπάνω κώδικας λέει βασικά, όταν μετακινούμε το επίπεδο αντικειμένου περισσότερο από 70 εικονοστοιχεία, στη συνέχεια αλλάξτε την κατάσταση στοιχείου σε κατάσταση «α». Μπορείτε να διαβάσετε σχετικά με το εάν οι δηλώσεις στην τεκμηρίωση του Framer Studio: https://framer.com/getstarted/programming/#conditional
Έχουμε σχεδόν τελειώσει με αυτήν την αλληλεπίδραση. Το μόνο που μένει είναι να αναιρέσετε αυτήν την ενέργεια:
item_bg.onTap -> item.stateCycle('default')
Θα πρέπει να είστε εξοικειωμένοι με αυτόν τον κωδικό από το προηγούμενο σεμινάριο.
Εάν θέλετε, μπορείτε να προσαρμόσετε το χρονοδιάγραμμα της κίνησης:
item.animationOptions = time: 0.75 curve: Spring
Αυτή είναι μια πολύ χρήσιμη αλληλεπίδραση για ενέργειες που απαιτούν φόρτωση ή χρόνους αναμονής για τον χρήστη. Όταν δημιουργούμε αυτήν την αλληλεπίδραση, θα μάθετε πώς να διαχειρίζεστε πολλά κινούμενα σχέδια που συμβαίνουν ένα προς ένα. Κατεβάστε το πρωτότυπο εδώ: https://framer.cloud/FxmHN
Δημιουργήστε ένα απλό κουμπί με τέσσερα επίπεδα: μια γραμμή προόδου και τρία εικονίδια για διαφορετικές καταστάσεις. Σχεδίασα το κουμπί μου με ένα εικονίδιο μεταφόρτωσης ορατό, μια γραμμή προόδου στο κάτω μέρος με πλάτος 0 και δύο ακόμη κρυμμένα εικονίδια.
Αυτό το ολόκληρο πρωτότυπο μπορεί να δημιουργηθεί χωρίς να γράφεται ούτε μία γραμμή κώδικα, απλά χρησιμοποιώντας τις λειτουργίες του αυτόματου κώδικα του Framer.
Πρώτα, προσθέστε ένα συμβάν. Θα ενεργοποιήσουμε ολόκληρη την αλληλεπίδραση με ένα πάτημα στο επίπεδο κουμπιών:
Αυτός είναι ο κωδικός που έγραψε ο Framer για εσάς:
button.onTap (event, layer) ->
Θα χρησιμοποιήσουμε τις λειτουργίες αυτόματου κωδικού του Framer για να σχεδιάσουμε όλες τις κινούμενες εικόνες:
Έχω σχεδιάσει τέσσερις κινούμενες εικόνες με διαφορετικό χρονισμό:
Εδώ είναι ο κωδικός που έγραψε ο Framer για καθένα από αυτά τα κινούμενα σχέδια:
# change progress bar width progress.animate width: 247 options: time: 1.4 curve: Bezier.ease # hide upload icon upload.animate opacity: 0.00 y: 39 options: time: 0.2 curve: Bezier.ease # show and rotate loader icon load.animate opacity: 1.00 rotation: 360 options: time: 1 curve: Bezier.ease # show and scale check icon done.animate opacity: 1.00 scale: 1.4 options: time: 0.2 curve: Bezier.ease delay: 1.00
Όπως ίσως έχετε παρατηρήσει, δεν κρύψαμε το εικονίδιο του φορτωτή μετά την ολοκλήρωση της κινούμενης εικόνας. Για να ολοκληρώσετε αυτό το πρωτότυπο, ενεργοποιήστε ένα άλλο κινούμενο σχέδιο χρησιμοποιώντας αυτό το συμβάν: load.onAnimationEnd ->
load.animate opacity: 0.00 options: time: 0.2 curve: Bezier.ease
Σχεδόν κάθε προϊόν με μια λίστα μέσα του χρησιμοποιεί αυτόν τον τύπο αλληλεπίδρασης. Ο χρήστης κατεβάζει ολόκληρη τη λίστα για να την ανανεώσει. Είναι πολύ εύκολο να δημιουργηθεί. Κατεβάστε το πρωτότυπο εδώ: https://framer.cloud/DgMDw
Μπορούμε να πηδήσουμε κατευθείαν στη λειτουργία σχεδίασης. Χρειαζόμαστε δύο πράγματα: μια λίστα και ένα εικονίδιο ανανέωσης. Το κρίσιμο πράγμα εδώ είναι να κρύψετε το εικονίδιο ανανέωσης με αδιαφάνεια και να το βάλετε στη λίστα μας:
Θέλουμε να κάνουμε τη λίστα μας με δυνατότητα κύλισης. Για να το κάνετε αυτό, χρησιμοποιήστε ένα στοιχείο κύλισης και προσθέστε ένα επίπεδο λίστας σε αυτό:
scroll = new ScrollComponent size: Screen scrollHorizontal: false list.parent = scroll.content
Δημιουργήστε μια απλή κατάσταση για το εικονίδιο:
icon.states.a = opacity: 1
Η λίστα μας έχει δυνατότητα κύλισης αυτήν τη στιγμή. Αυτό σημαίνει ότι όταν κάνουμε κύλιση προς τα πάνω ή προς τα κάτω, ολόκληρο το περιεχόμενο κύλισης κινείται στον άξονα «y». Με αυτές τις γνώσεις, μπορούμε να δημιουργήσουμε μια εκδήλωση:
scroll.content.onMove -> if scroll.content.y > 180 icon.stateCycle('a')
Και πάλι χρησιμοποιούμε μια δήλωση «if». Εάν η λίστα τραβηχτεί προς τα κάτω (μετακινηθεί στον άξονα y) πάνω από 180 εικονοστοιχεία, θα ενεργοποιήσουμε μια ενέργεια. Σε αυτήν την περίπτωση, θα κινούσουμε δύο επίπεδα: τη λίστα και το εικονίδιο ανανέωσης.
scroll.content.onMove -> if scroll.content.y > 180 icon.stateCycle('a') list.animate y: 210 options: time: 1 curve: Bezier.ease refresh.animate rotation: 360 options: time: 1
Χρησιμοποιούμε το 'animate' για να μετακινήσουμε τη λίστα κάτω από τα 210 εικονοστοιχεία και να περιστρέψουμε το εικονίδιο ανανέωσης 360 °.
Το πρωτότυπο λειτουργεί σχεδόν, αλλά πρέπει να επαναφέρουμε όλα τα επίπεδα μετά την ανανέωση του animation. Για να το κάνουμε αυτό, θα χρησιμοποιήσουμε ένα συμβάν αφού τελειώσει η κινούμενη εικόνα:
icon.onAnimationEnd ->
Κινούμαστε την περιστροφή του εικονιδίου ανανέωσης στην αρχική του θέση και χρησιμοποιώντας τον κύκλο κατάστασης, επαναφέρουμε την κατάσταση φόντου λίστας και εικονιδίου:
scroll.content.onMove -> if scroll.content.y > 180 icon.stateCycle('a') list.animate y: 210 options: time: 1 curve: Bezier.ease refresh.animate rotation: 360 options: time: 1 icon.onAnimationEnd -> refresh.animate rotation: 0 list.stateCycle('default') icon.stateCycle('default')
Αυτό είναι!
Έχετε παρατηρήσει ποτέ ότι ενώ σύρετε ένα στοιχείο μέσα σε μια εφαρμογή, πάντα συμβαίνει κάτι με το ίδιο το αντικείμενο; Μερικές φορές το στοιχείο συρρικνώνεται, ίσως άλλα αντικείμενα είναι θολά ή η αδιαφάνεια αλλάζει. Ας μάθουμε πώς να δημιουργούμε αυτού του είδους την αλληλεπίδραση. Κατεβάστε το πρωτότυπο εργασίας εδώ: https://framer.cloud/YstiW
Δημιουργήστε ένα πλέγμα πλακιδίων και βεβαιωθείτε ότι βρίσκονται μέσα στο γονικό στοιχείο.
'for
βρόχος »μπορεί να ακούγεται τρομακτικό, αλλά είναι πραγματικά απλό. Εάν δεν είστε εξοικειωμένοι με for
βρόχους, μπορείτε να διαβάσετε πρώτα λίγο φόντο: https://framer.com/getstarted/programming/#loops-and-arrays
Θα χρησιμοποιήσουμε το for
βρόχο για στόχευση όλων των πλακιδίων μέσα στο πλέγμα μας:
for item in grid.subLayers
Με αυτήν την απλή γραμμή κώδικα, στοχεύσατε όλα τα επίπεδα μέσα στο επίπεδο πλέγματος.
Κάντε κάθε στοιχείο μέσα στο πλέγμα με δυνατότητα μεταφοράς:
for item in grid.subLayers item.draggable = true
Όλα τα στοιχεία πρέπει να έχουν κατάσταση κατά τη μεταφορά τους. Πρέπει να ξεκινήσετε από τον κώδικα, αλλά αργότερα θα μπορείτε να επεξεργαστείτε αυτήν την κατάσταση στο Layer Editor:
for item in grid.subLayers item.draggable = true item.states.a = scale: 1.1 shadowBlur: 50 shadowColor: 'rgba(0,0,0,0.5)'
Πρέπει να δημιουργήσουμε συμβάντα για να ενεργοποιήσουμε διαφορετικές καταστάσεις κατά τη μεταφορά του αντικειμένου. Το πρώτο συμβάν θα ενεργοποιήσει μια ενέργεια ενώ αρχίζουμε να σύρουμε:
for item in grid.subLayers item.draggable = true item.states.a = scale: 1.1 shadowBlur: 50 shadowColor: 'rgba(0,0,0,0.5)' item.onDragStart -> this.bringToFront() this.stateCycle('a')
Χρησιμοποίησα this.bringToFront()
για να βεβαιωθείτε ότι το αντικείμενο βρίσκεται πάντα πάνω από τα άλλα επίπεδα.
Ο δεύτερος κανόνας θα επαναφέρει την κατάσταση του στοιχείου:
for item in grid.subLayers item.draggable = true item.states.a = scale: 1.1 shadowBlur: 50 shadowColor: 'rgba(0,0,0,0.5)' item.onDragStart -> this.bringToFront() this.stateCycle('a') item.onDragEnd -> this.sendToBack() this.stateCycle('default')
Σε αυτό το σημείο, έχουμε ένα πρωτότυπο που λειτουργεί.
Η αλληλεπίδραση συμβαίνει πάντα κατά τη διάρκεια του χρονικού πλαισίου. Είναι καλό να προσαρμόσετε το χρονοδιάγραμμα για να επιτύχετε ένα τέλειο αποτέλεσμα:
for item in grid.subLayers item.draggable = true item.states.a = scale: 1.1 shadowBlur: 50 shadowColor: 'rgba(0,0,0,0.5)' item.onDragStart -> this.bringToFront() this.stateCycle('a') item.onDragEnd -> this.sendToBack() this.stateCycle('default') item.animationOptions = time: 0.3 curve: Spring
Σε αυτό το πρωτότυπο, θα χρησιμοποιήσουμε πιο προηγμένες τεχνικές για να σας δείξουμε έναν διαφορετικό τρόπο στόχευσης επιπέδων στο Framer Studio, το οποίο θα δημιουργήσει πιο ευαίσθητες αλληλεπιδράσεις με λιγότερο χρόνο. Εάν δεν είστε εξοικειωμένοι με τη βασική κωδικοποίηση, σας προτείνω να διαβάσετε πρώτα αυτό το άρθρο: https://blog.framer.com/code-less-achieve-more-with-arrays-in-framer-c43594d13d59
Για αυτήν την αλληλεπίδραση, θα παραλείψουμε το σχέδιο και θα χρησιμοποιήσουμε ένα πρωτότυπο που έχω δημιουργήσει ειδικά για αυτό το άρθρο: https://framer.cloud/SZMCH
Ρίξτε μια ματιά στη δομή των επιπέδων μέσα στο Framer Studio:
Έχουμε ένα «κουμπί» μέσα σε μια «σειρά» στην ομάδα «λίστα». Θα δημιουργήσουμε μια αλληλεπίδραση στα επίπεδα των κουμπιών, οπότε πρέπει να τα στοχεύσουμε. Αλλά πρώτα, πρέπει να βρούμε όλα τα επίπεδα γραμμών και να τα βάλουμε μέσα σε έναν πίνακα:
rows = list.children buttons = []
Έχω δημιουργήσει επίσης έναν κενό πίνακα για όλα τα επίπεδα 'κουμπιών': buttons = []
.
Ας ξεκινήσουμε από το 'για βρόχο':
for i in rows buttons.push(i.children[0])
Για να προσθέσουμε επίπεδα στον πίνακα, θα χρησιμοποιήσουμε: buttons.push()
. Αυτό σημαίνει ότι βάζουμε το πρώτο επίπεδο κάθε ομάδας «σειρά» μέσα σε έναν πίνακα.
Τώρα θα δημιουργήσουμε μια κατάσταση για τα κουμπιά 'like' και θα προσθέσουμε ένα συμβάν σε αυτά πατώντας:
for i in buttons i.states.a = scale: 1.2 hueRotate: -80 i.onTap -> this.stateCycle() i.animationOptions = time: 0.3 curve: Spring
Μπορείτε να χρησιμοποιήσετε αυτήν την τεχνική για να αναδημιουργήσετε όλα τα προηγούμενα πρωτότυπα και να τα κάνετε πιο περίπλοκα.
Όταν δημιουργείτε μικρο-αλληλεπιδράσεις, εστιάζετε στις μικρότερες λεπτομέρειες. Μπορείτε να δημιουργήσετε κινούμενα σχέδια που ενεργοποιούνται από οποιονδήποτε τύπο δράσης και να τα κάνετε τέλεια. Λάβετε υπόψη ότι υπάρχουν εκατοντάδες τρόποι για να δημιουργήσετε το ίδιο πρωτότυπο και θα πρέπει να χρησιμοποιήσετε τη μέθοδο που ταιριάζει στις δεξιότητές σας και στις ανάγκες των σχεδίων προϊόντων σας.
• • •