Πώς να δημιουργήσετε ένα spinner φόρτωσης εμπνευσμένο από το Reddit με μόνο HTML και CSS

Η εφαρμογή για κινητά του Reddit έχει έναν εντυπωσιακό περιστρεφόμενο κλώστη που θυμίζει τροχιακά σώματα που περιβάλλουν έναν πλανήτη ή ένα αστέρι. Οι περισσότεροι προγραμματιστές θα έφταναν για JavaScript ή SVG για μια τέτοια εργασία, αλλά χάρη σε αυτόanimation-iteration-count: infinite;και μερικά άλλα hacks και κόλπα, αυτό δεν είναι καν απαραίτητο. Σήμερα πρόκειται να σας δείξω πώς να κωδικοποιήσετε ένα spinner εμπνευσμένο από το Reddit αποκλειστικά σε HTML και CSS!

Εδώ είναι το τελικό αποτέλεσμα:

Βασική ρύθμιση

Ας ξεκινήσουμε γράφοντας ορισμένα στοιχεία HTML DOM στα οποία μπορούμε να καρφιτσώσουμε τον κεντρικό κύκλο και καθένα από τα περιστρεφόμενα τροχιακά.

 ... ... 

Τα στοιχεία inner-spinκαι τα outer-spinστοιχεία θα είναι οι γονικοί κόμβοι όλων όσων πρέπει να είναι κινούμενα και τελικά θα εφαρμόσουμε τις μετασχηματισμένες βασικές ρυθμίσεις CSS σε αυτούς τους γονικούς κόμβους.

Στο παραπάνω παράδειγμα κώδικα, οι ελλείψεις ( ) αντιστοιχούν στα τόξα και σε τροχιά γύρω από «φεγγάρια». Τόσο ο εσωτερικός όσο και ο εξωτερικός δακτύλιος το καθένα περιέχουν δύο τόξα και δύο φεγγάρια, αλλά για λόγους που θα γίνουν σαφείς λίγο αργότερα, κάθε τόξο αποτελείται πραγματικά από δύο σχήματα CSS, επομένως χρειαζόμαστε συνολικά οκτώ τόξα και τέσσερα φεγγάρια. Το HTML σε πλήρη εμφάνιση μοιάζει με αυτό:

Σχήματα CSS

Είναι δυνατόν να σχεδιάσετε κύκλους και τόξα σε CSS δημιουργώντας απλώς ένα τετράγωνο και ρυθμίζοντας border-radiusστο 50%.

Κάθε πλευρά του περιγράμματος μπορεί να έχει διαφορετικό χρώμα ή μπορεί να ρυθμιστεί σε transparent. Η background-colorιδιότητα ορίζει το γέμισμα του σχήματος, εάν υπάρχει.

Είναι εύκολο να σχεδιάσετε τόξα 90, 180 και 270 μοιρών ρυθμίζοντας απλώς μια ή περισσότερες πλευρές του περιγράμματος ώστε να είναι διαφανής. Ωστόσο, εάν κοιτάξετε προσεκτικά τον περιστρεφόμενο στην κορυφή της σελίδας, θα παρατηρήσετε ότι η «ουρά» κάθε τροχιακής αφήνει ένα κενό μεταξύ του και του φεγγαριού πίσω από αυτό. Αυτό σημαίνει ότι, αν και το μήκος του τόξου είναι κοντά στους 180 μοίρες, είναι λίγο ντροπαλό των 180.

Για να σχεδιάσετε τμήματα κύκλων με ακανόνιστα μήκη στο CSS απαιτείται λίγο χάκετ. Για να γίνει αυτό, πρέπει να σχεδιάσουμε δύο παρακείμενα τμήματα τόξου 90 μοιρών και να περιστρέψουμε ένα ελαφρώς έτσι ώστε να επικαλύπτονται, αφήνοντας ένα φαινόμενο τμήμα τόξου περίπου 160 μοιρών.

Κοιτάζοντας πίσω το HTML τώρα, ίσως τώρα μπορείτε να μαντέψετε γιατί έχουμε ορίσει δύο κόμβους για κάθε τόξο (an arc_startκαι arc_end). Αυτά θα χρησιμοποιηθούν για την αναπαράσταση κάθε μέρους ενός μοναδικού επικαλυπτόμενου τόξου που αντιπροσωπεύει την ουρά κάθε τροχιάς.

Ρύθμιση του CSS

Αρχικά, θα ορίσουμε μια μεταβλητή CSS που θα αντιπροσωπεύει το χρώμα του περιστρεφόμενου και μια άλλη μεταβλητή που θα αντιπροσωπεύει μια μετάφραση -50%, -50% την οποία θα χρησιμοποιήσουμε σε όλο το CSS για να κεντράρουμε σχήματα γύρω από το κέντρο τους (όπως φαίνεται στο στην επάνω αριστερή γωνία τους, που είναι η προεπιλογή).

html { --spinner: #1EAAF0; --center: translate(-50%, -50%); }

Τώρα μπορούμε να προχωρήσουμε και να σχεδιάσουμε τον κεντρικό κύκλο επίσης.

.center { position: absolute; width: 30px; height: 30px; background: var(--spinner); border-radius: 50%; top: 50%; left: 50%; transform: var(--center); }

Οι θυγατρικοί κόμβοι για κάθε τροχιακό εγκλείονται μέσα στους γονικούς κόμβους που ονομάζονται inner-spinκαι outer-spin. Προς το παρόν θα τα χρησιμοποιήσουμε για να κεντράρουμε τον κλώστη μέσα στο παράθυρο.

.outer-spin, .inner-spin { position: absolute; top: 50%; left: 50%; }

Σχεδίαση των τροχιακών

Ο κλώστης φόρτωσης είναι βασικά μια σειρά ομόκεντρων κύκλων, οπότε ας επικεντρωθούμε πρώτα στην σχεδίαση μόνο ενός τόξου.

Δεδομένου ότι κάθε τόξο αποτελείται από δύο αλληλεπικαλυπτόμενα τμήματα, ας αρχίσουμε να σχεδιάζουμε μόνο δύο τόξα το ένα δίπλα στο άλλο.

.inner-arc { width: 62px; height: 62px; } .inner-arc_start-a { border-color: transparent transparent transparent green; /* NOTE: the order here very much matters! */ transform: var(--center) rotate(0deg); } .inner-arc_end-a { border-color: red transparent transparent transparent; transform: var(--center) rotate(0deg); }

Ο πρώτος μετασχηματισμός κεντράρει το παράθυρο. Η περιστροφή ρυθμίζεται σε μηδέν μοίρες για να δείχνει την προεπιλεγμένη κατάσταση των τόξων.

Παρατηρήστε ότι τα τόξα δεν ευθυγραμμίζονται με τις διασταυρώσεις x στον κύκλο μονάδας. Για να το διορθώσουμε και για να διευκολύνουμε την επεξεργασία των τόξων, περιστρέφουμε τα τόξα κατά 45 μοίρες. Στη συνέχεια περιστρέφουμε λίγο πάνω από ένα τόξο για να δημιουργήσουμε ένα συνολικό μήκος τόξου περίπου 160 μοίρες.

.inner-arc_start-a { border-color: transparent transparent transparent green; transform: var(--center) rotate(65deg); } .inner-arc_end-a { border-color: red transparent transparent transparent; transform: var(--center) rotate(45deg); }

Next we can position one of the orbital moons by moving it along the x-axis. Unfortunately, unlike vector graphics such as SVGs, CSS borders are not widthless vectors that accept a stroke style. That means that distances are not automatically measured to the center point of the line. We must take into account the width of the border when positioning objects.

This results in a few “magic numbers” that we could probably minimize if we wanted to set more CSS variables and use the calc() function. That seems a bit involved though, so I’ll just position the circle by pixel value for now.

.inner-moon-a { position: absolute; top:50%; left:50%; width: 12px; height: 12px; background: red; border-radius: 50%; transform: var(--center) translate(33px, 0); }

Next we draw two more arcs, but this time we use the scale(-1, -1) transform. This flips the arcs across both the x- and y-axes, essentially mirroring the contrail.

.inner-arc_start-b { border-color: transparent transparent transparent var(--spinner); transform: var(--center) rotate(65deg) scale(-1, -1); } .inner-arc_end-b { border-color: var(--spinner) transparent transparent transparent; transform: var(--center) rotate(45deg) scale(-1, -1);

Finally, for the outer orbit, we simply repeat the CSS from the inner orbit but set a larger height and width! (Imagine how short this CSS could be with SASS mixins!)

.outer-arc { width: 100px; height: 100px; }

Adding the Animation

The last step is to add animation. First we need to add a single keyframes element that sets the type of animation behavior and the CSS element(s) effected by animation, in this case rotation through a transform property.

@keyframes spin { 100% {transform: rotate(360deg); } }

The identifier “spin” connects the keyframes back to animation attributes that we will add within each parent elements. The animation property sets the temporal information for the animation, meaning that each orbital will orbit at a different speed.

.outer-spin { animation: spin 4s linear infinite; } .inner-spin { animation: spin 3s linear infinite; }

That’s it!

Ο κωδικός για αυτό το σεμινάριο μπορεί να βρεθεί στο CodePen.io. Παρακαλώ σχολιάστε - ή Tweet σε μένα @PleathrStarfish - εάν έχετε μια πρόταση, παρατήρηση ή ένα δροσερό πιρούνι του κώδικα μου!