Πρόσφατα δημιούργησα ένα μοτίβο τοίχου από τούβλα ως μέρος μου #PetitePatterns σειρά, μια πρόκληση όπου δημιουργώ μοτίβα ή υφές με οργανική εμφάνιση σε SVG εντός 560 byte (ή περίπου στο μέγεθος δύο tweets). Για να ανταποκριθώ σε αυτόν τον περιορισμό, έχω περάσει από ένα ταξίδι που μου έμαθε ορισμένους ριζοσπαστικούς τρόπους βελτιστοποίησης των μοτίβων SVG, ώστε να περιέχουν όσο το δυνατόν λιγότερο κώδικα χωρίς να επηρεάζεται η συνολική ποιότητα της εικόνας.
Θέλω να σας καθοδηγήσω στη διαδικασία και να σας δείξω πώς μπορούμε να πάρουμε ένα μοτίβο SVG που ξεκινά από τα 197 byte μέχρι τα 44 byte - μια τεράστια μείωση 77.7%!
Το μοτίβο SVG
Αυτό είναι αυτό που ονομάζεται μοτίβο τούβλου "τρέχοντος δεσμού". Είναι το πιο συνηθισμένο μοτίβο από τούβλα εκεί έξω, και ένα που σίγουρα έχετε ξαναδεί: κάθε σειρά τούβλων αντισταθμίζεται κατά το ήμισυ του μήκους ενός τούβλου, δημιουργώντας ένα επαναλαμβανόμενο κλιμακωτό μοτίβο. Η διάταξη είναι αρκετά απλή, καθιστώντας τα SVG <pattern>
στοιχείο που ταιριάζει απόλυτα για την αναπαραγωγή του σε κώδικα.
Το SVG <pattern>
Το στοιχείο χρησιμοποιεί ένα προκαθορισμένο γραφικό αντικείμενο το οποίο μπορεί να αναπαραχθεί (ή να "πλακώσει") σε σταθερά διαστήματα κατά μήκος του οριζόντιου και του κατακόρυφου άξονα. Ουσιαστικά, ορίζουμε ένα ορθογώνιο σχέδιο πλακιδίων και επαναλαμβάνεται για να βάψουμε την περιοχή πλήρωσης.
Αρχικά, ας ορίσουμε τις διαστάσεις ενός τούβλου και το κενό μεταξύ κάθε τούβλου. Για λόγους απλότητας, ας χρησιμοποιήσουμε καθαρούς, στρογγυλούς αριθμούς: πλάτος από 100
και ύψος 30
για το τούβλο, και 10
για τα οριζόντια και κάθετα κενά μεταξύ τους.
Στη συνέχεια, πρέπει να προσδιορίσουμε το πλακίδιο «βάσης» μας. Και με το "πλακάκι" μιλάω για πλακάκια μοτίβου παρά για φυσικά πλακάκια, που δεν πρέπει να συγχέονται με τα τούβλα. Ας χρησιμοποιήσουμε το επισημασμένο τμήμα της παραπάνω εικόνας ως πλακίδιο μοτίβου: δύο ολόκληρα τούβλα στην πρώτη σειρά και ένα ολόκληρο στριμωγμένο ανάμεσα σε δύο μισά τούβλα στη δεύτερη σειρά. Παρατηρήστε πώς και πού περιλαμβάνονται τα κενά, επειδή αυτά πρέπει να συμπεριληφθούν στο πλακίδιο επαναλαμβανόμενου σχεδίου.
Οταν χρησιμοποιείτε <pattern>
, πρέπει να ορίσουμε το μοτίβο width
και height
, που αντιστοιχούν στο πλάτος και το ύψος του πλακιδίου βάσης. Για να πάρουμε τις διαστάσεις, χρειαζόμαστε λίγα μαθηματικά:
Tile Width = 2(Brick Width) + 2(Gap) = 2(100) + 2(10) = 220
Tile Height = 2(Bright Height) + 2(Gap) = 2(30) + 2(10) = 80
Εντάξει, έτσι το πλακίδιο μοτίβο μας είναι 220✕80
. Πρέπει επίσης να ρυθμίσουμε το patternUnits
χαρακτηριστικό, όπου η τιμή userSpaceOnUse
ουσιαστικά σημαίνει pixels. Τέλος, προσθέτοντας ένα id
στο σχέδιο είναι απαραίτητο για να μπορεί να γίνει αναφορά όταν ζωγραφίζουμε ένα άλλο στοιχείο με αυτό.
<pattern id="p" width="220" height="80" patternUnits="userSpaceOnUse"> <!-- pattern content here -->
</pattern>
Τώρα που έχουμε καθορίσει τις διαστάσεις του πλακιδίου, η πρόκληση είναι να δημιουργήσουμε τον κώδικα για το πλακίδιο με τρόπο που να αποδίδει το γραφικό με τον μικρότερο δυνατό αριθμό byte. Αυτό είναι που ελπίζουμε να καταλήξουμε στο τέλος:
Αρχική σήμανση (197 byte)
Η απλούστερη και πιο δηλωτική προσέγγιση για να αναδημιουργήσω αυτό το μοτίβο που μου έρχεται στο μυαλό είναι να σχεδιάσω πέντε ορθογώνια. Από προεπιλογή, το fill
ενός στοιχείου SVG είναι μαύρο και το stroke
είναι διαφανές. Αυτό λειτουργεί καλά για τη βελτιστοποίηση των μοτίβων SVG, καθώς δεν χρειάζεται να τα δηλώνουμε ρητά στον κώδικα.
Κάθε γραμμή στον παρακάτω κώδικα ορίζει ένα ορθογώνιο. ο width
και height
είναι πάντα ρυθμισμένα, και το x
και y
Οι θέσεις ορίζονται μόνο εάν ένα ορθογώνιο είναι μετατοπισμένο από το 0
θέση.
<rect width="100" height="30"/>
<rect x="110" width="100" height="30"/>
<rect y="40" width="45" height="30"/>
<rect x="55" y="40" width="100" height="30"/>
<rect x="165" y="40" width="55" height="30"/>
Η επάνω σειρά του πλακιδίου περιείχε δύο τούβλα πλήρους πλάτους, το δεύτερο τούβλο είναι τοποθετημένο σε x="110"
επιτρέποντας 10
pixels του κενού πριν από το τούβλο. Παρομοίως υπάρχει 10
pixels του κενού μετά, επειδή το τούβλο τελειώνει σε 210
εικονοστοιχεία (110 + 100 = 210
) στον οριζόντιο άξονα παρόλο που η <pattern>
το πλάτος είναι 220
εικονοστοιχεία. Χρειαζόμαστε αυτό το λίγο επιπλέον χώρο. διαφορετικά το δεύτερο τούβλο θα συγχωνευόταν με το πρώτο τούβλο στο διπλανό πλακίδιο.
Τα τούβλα στη δεύτερη (κάτω) σειρά είναι μετατοπισμένα, έτσι ώστε η σειρά περιέχει δύο μισά τούβλα και ένα ολόκληρο τούβλο. Σε αυτήν την περίπτωση, θέλουμε τα τούβλα μισού πλάτους να συγχωνευθούν, ώστε να μην υπάρχει κενό στην αρχή ή στο τέλος, επιτρέποντάς τους να ρέουν απρόσκοπτα με τα τούβλα σε παρακείμενα πλακάκια μοτίβου. Κατά την αντιστάθμιση αυτών των τούβλων, πρέπει επίσης να συμπεριλάβουμε μισά κενά, επομένως το x
οι αξίες είναι 55
και 165
, Αντίστοιχα.
Επαναχρησιμοποίηση στοιχείων, (-43B, 154B σύνολο)
Φαίνεται αναποτελεσματικό να ορίσουμε κάθε τούβλο τόσο ρητά. Δεν υπάρχει κάποιος τρόπος να βελτιστοποιήσετε τα μοτίβα SVG επαναχρησιμοποιώντας τα σχήματα;
Δεν νομίζω ότι είναι ευρέως γνωστό ότι το SVG έχει α <use>
στοιχείο. Μπορείτε να αναφέρετε ένα άλλο στοιχείο με αυτό και να αποδώσετε αυτό το στοιχείο αναφοράς οπουδήποτε <use>
χρησιμοποιείται. Αυτό εξοικονομεί αρκετά byte επειδή μπορούμε να παραλείψουμε να καθορίσουμε τα πλάτη και τα ύψη κάθε τούβλου, εκτός από το πρώτο.
Εχοντας πεί αυτό, <use>
έρχεται με μια μικρή τιμή. Δηλαδή πρέπει να προσθέσουμε ένα id
για το στοιχείο που θέλουμε να επαναχρησιμοποιήσουμε.
<rect id="b" width="100" height="30"/>
<use href="#b" x="110"/>
<use href="#b" x="-55" y="40"/>
<use href="#b" x="55" y="40"/>
<use href="#b" x="165" y="40"/>
Το πιο σύντομο id
είναι δυνατός ένας χαρακτήρας, γι' αυτό επέλεξα το "b" για τούβλο. ο <use>
το στοιχείο μπορεί να τοποθετηθεί παρόμοια με <rect>
, με την x
και y
ιδιότητες ως μετατοπίσεις. Δεδομένου ότι κάθε τούβλο έχει όλο το πλάτος τώρα που έχουμε αλλάξει <use>
(θυμηθείτε, μειώσαμε ρητά στο μισό τα τούβλα στη δεύτερη σειρά του πλακιδίου μοτίβου), πρέπει να χρησιμοποιήσουμε ένα αρνητικό x
τιμή στη δεύτερη σειρά και, στη συνέχεια, βεβαιωθείτε ότι το τελευταίο τούβλο ξεχειλίζει από το πλακίδιο για αυτήν την απρόσκοπτη σύνδεση μεταξύ των τούβλων. Αυτά είναι εντάξει, ωστόσο, επειδή οτιδήποτε πέφτει έξω από το πλακίδιο μοτίβου κόβεται αυτόματα.
Μπορείτε να εντοπίσετε μερικές επαναλαμβανόμενες χορδές που μπορούν να γραφτούν πιο αποτελεσματικά; Ας δουλέψουμε σε αυτά στη συνέχεια.
Επανεγγραφή στη διαδρομή (-54B, 100B συνολικά)
<path>
είναι ίσως το πιο ισχυρό στοιχείο στο SVG. Μπορείτε να σχεδιάσετε σχεδόν οποιοδήποτε σχήμα με "εντολές" μέσα του d
Χαρακτηριστικό. Υπάρχουν 20 διαθέσιμες εντολές, αλλά χρειαζόμαστε μόνο τις απλούστερες για ορθογώνια.
Να που κατέληξα με αυτό:
<path d="M0 0h100v30h-100z M110 0h100v30h-100 M0 40h45v30h-45z M55 40h100v30h-100z M165 40h55v30h-55z"/>
Ξέρω, πολύ περίεργοι αριθμοί και γράμματα! Όλα έχουν νόημα, φυσικά. Δείτε τι συμβαίνει στη συγκεκριμένη περίπτωση:
M{x} {y}
: Μετακινείται σε ένα σημείο με βάση συντεταγμένες.z
: Κλείνει το τρέχον τμήμα.h{x}
: Σχεδιάζει μια οριζόντια γραμμή από το τρέχον σημείο, με μήκος απόx
προς την κατεύθυνση που ορίζεται από το σύμβολο τουx
. Πεζά γράμματαx
δείχνει μια σχετική συντεταγμένη.v{y}
: Σχεδιάζει μια κατακόρυφη γραμμή από το τρέχον σημείο, με μήκοςy
προς την κατεύθυνση που ορίζεται από το σύμβολο τουy
. Πεζά γράμματαy
δείχνει μια σχετική συντεταγμένη.
Αυτή η σήμανση είναι πολύ πιο συνοπτική από την προηγούμενη (οι αλλαγές γραμμής και τα κενά εσοχές είναι μόνο για αναγνωσιμότητα). Και, φευ, καταφέραμε να κόψουμε το μισό από το αρχικό μέγεθος, φτάνοντας στα 100 byte. Ωστόσο, κάτι με κάνει να νιώθω ότι αυτό θα μπορούσε να είναι μικρότερο…
Αναθεώρηση πλακιδίων (-38B, 62B σύνολο)
Το πλακίδιο μοτίβου μας δεν έχει επαναλαμβανόμενα μέρη; Είναι σαφές ότι στην πρώτη σειρά επαναλαμβάνεται ένα ολόκληρο τούβλο, αλλά τι γίνεται με τη δεύτερη σειρά; Είναι λίγο πιο δύσκολο να το δούμε, αλλά αν κόψουμε το μεσαίο τούβλο στη μέση γίνεται προφανές.
Λοιπόν, το μεσαίο τούβλο δεν είναι ακριβώς κομμένο στη μέση. Υπάρχει μια μικρή αντιστάθμιση γιατί πρέπει επίσης να λάβουμε υπόψη το κενό. Τέλος πάντων, μόλις βρήκαμε ένα πιο απλό μοτίβο πλακιδίων βάσης, που σημαίνει λιγότερα byte! Αυτό σημαίνει επίσης ότι πρέπει να μειώσουμε το μισό width
των μας <pattern>
στοιχείο από 220 έως 110.
<pattern id="p" width="110" height="80" patternUnits="userSpaceOnUse"> <!-- pattern content here -->
</pattern>
Τώρα ας δούμε πώς σχεδιάζεται το απλοποιημένο πλακίδιο <path>
:
<path d="M0 0h100v30h-100z M0 40h45v30h-45z M55 40h55v30h-55z"/>
Το μέγεθος μειώνεται στα 62 byte, που είναι ήδη λιγότερο από το ένα τρίτο του αρχικού μεγέθους! Αλλά γιατί να σταματήσουμε εδώ όταν μπορούμε να κάνουμε ακόμη περισσότερα!
Συντόμευση εντολών διαδρομής (-9B, 53B συνολικά)
Αξίζει να μπούμε λίγο πιο βαθιά σε αυτό <path>
στοιχείο επειδή παρέχει περισσότερες συμβουλές για τη βελτιστοποίηση των μοτίβων SVG. Μια παρανόηση που είχα όταν δούλευα μαζί του <path>
αφορά το πώς το fill
χαρακτηριστικό λειτουργεί. Έχοντας παίξει πολύ με το MS Paint στα παιδικά μου χρόνια, έμαθα ότι όποιο σχήμα θέλω να γεμίσω με μονόχρωμο πρέπει να είναι κλειστό, δηλαδή να μην έχει ανοιχτά σημεία. Διαφορετικά, το χρώμα θα διαρρεύσει από το σχήμα και θα χυθεί πάνω από τα πάντα.
Στο SVG, ωστόσο, αυτό δεν είναι αλήθεια. Επιτρέψτε μου να παραθέσω το spec από μόνη της:
Η λειτουργία πλήρωσης γεμίζει ανοιχτές υποδιαδρομές εκτελώντας τη λειτουργία πλήρωσης σαν να προστέθηκε μια πρόσθετη εντολή "closepath" στη διαδρομή για να συνδέσει το τελευταίο σημείο της υποδιαδρομής με το πρώτο σημείο της υποδιαδρομής.
Αυτό σημαίνει ότι μπορούμε να παραλείψουμε τις εντολές κλεισίματος διαδρομής (z
), επειδή οι δευτερεύουσες διαδρομές θεωρούνται αυτόματα κλειστές όταν γεμίζονται.
Ένα άλλο χρήσιμο πράγμα που πρέπει να γνωρίζετε για τις εντολές διαδρομής είναι ότι διατίθενται σε παραλλαγές κεφαλαίων και πεζών. Τα πεζά γράμματα σημαίνουν ότι χρησιμοποιούνται σχετικές συντεταγμένες. Αντ' αυτού χρησιμοποιούνται κεφαλαία γράμματα που σημαίνει απόλυτες συντεταγμένες.
Είναι λίγο πιο δύσκολο από αυτό με το H
και V
εντολές γιατί περιλαμβάνουν μόνο μία συντεταγμένη. Να πώς θα περιέγραφα αυτές τις δύο εντολές:
H{x}
: Σχεδιάζει μια οριζόντια γραμμή από το τρέχον σημείο για να συντείνειx
.V{y}
: Σχεδιάζει μια κάθετη γραμμή από το τρέχον σημείο για να συντονίσειy
.
Όταν σχεδιάζουμε το πρώτο τούβλο στο πλακίδιο μοτίβο, ξεκινάμε από το (0,0)
συντεταγμένες. Στη συνέχεια σχεδιάζουμε μια οριζόντια γραμμή προς (100,0)
και μια κάθετη γραμμή προς (100,30)
, και τέλος, σχεδιάστε μια οριζόντια γραμμή προς (0,30)
. Χρησιμοποιήσαμε το h-100
εντολή στην τελευταία γραμμή, αλλά είναι το ισοδύναμο του H0
, που είναι δύο byte αντί για πέντε. Μπορούμε να αντικαταστήσουμε δύο παρόμοιες εμφανίσεις και να διαγράψουμε τον κωδικό μας <path>
μέχρι αυτό:
<path d="M0 0h100v30H0 M0 40h45v30H0 M55 40h55v30H55"/>
Άλλα 9 byte ξυρίστηκαν — πόσο μικρότερα μπορούμε να κάνουμε;
Γεφύρωση (-5B, 48B σύνολο)
Οι μεγαλύτερες εντολές που εμποδίζουν ένα πλήρως βελτιστοποιημένο μοτίβο SVG είναι οι εντολές "μετακίνηση σε" που καταλαμβάνουν 4, 5 και 6 byte, αντίστοιχα. Ένας περιορισμός που έχουμε είναι ότι:
Ένα τμήμα δεδομένων διαδρομής (αν υπάρχει) πρέπει να ξεκινά με μια εντολή "moveto".
Αλλά αυτό είναι εντάξει. Το πρώτο πάντως είναι το πιο σύντομο. Αν ανταλλάξουμε τις σειρές, μπορούμε να βρούμε έναν ορισμό διαδρομής όπου θα πρέπει μόνο να κινηθούμε είτε οριζόντια είτε κάθετα μεταξύ των τούβλων. Τι θα γινόταν αν μπορούσαμε να χρησιμοποιήσουμε το h
και v
εντολές εκεί αντί για M
?
Το παραπάνω διάγραμμα δείχνει πώς τα τρία σχήματα μπορούν να σχεδιαστούν με ένα μόνο μονοπάτι. Σημειώστε ότι αξιοποιούμε το γεγονός ότι το fill
η λειτουργία κλείνει αυτόματα το ανοιχτό τμήμα μεταξύ (110,0)
και (0,0)
. Με αυτήν την αναδιάταξη, μετακινήσαμε επίσης το κενό στα αριστερά του τούβλου πλήρους πλάτους στη δεύτερη σειρά. Δείτε πώς φαίνεται ο κώδικας, ακόμα σπασμένος σε ένα τούβλο ανά γραμμή:
<path d="M0 0v30h50V0 h10v30h50 v10H10v30h100V0"/>
Σίγουρα, βρήκαμε την απόλυτη μικρότερη λύση τώρα που έχουμε πέσει στα 48 byte, σωστά;! Καλά…
Περικοπή ψηφίων (-4B, 44B σύνολο)
Εάν μπορείτε να είστε λίγο ευέλικτοι με τις διαστάσεις, υπάρχει ένας άλλος μικρός τρόπος να βελτιστοποιήσουμε τα μοτίβα SVG. Δουλεύαμε με πλάτος τούβλου 100
pixel, αλλά είναι τρία byte. Αλλάζοντάς το σε 90
σημαίνει ένα byte λιγότερο όποτε πρέπει να το γράψουμε. Ομοίως, χρησιμοποιήσαμε ένα κενό του 10
pixel — αλλά αν το αλλάξουμε σε 8
Αντίθετα, αποθηκεύουμε ένα byte σε καθεμία από αυτές τις εμφανίσεις.
<path d="M0 0v30h45V0 h8v30h45 v8H8v30h90V0"/>
Φυσικά, αυτό σημαίνει επίσης ότι πρέπει να προσαρμόσουμε τις διαστάσεις του σχεδίου ανάλογα. Ακολουθεί ο τελικός βελτιστοποιημένος κώδικας μοτίβου SVG:
<pattern id="p" width="98" height="76" patternUnits="userSpaceOnUse"> <path d="M0 0v30h45V0h8v30h45v8H8v30h90V0"/>
</pattern>
Η δεύτερη γραμμή στο παραπάνω απόσπασμα — χωρίς να υπολογίζονται οι εσοχές — είναι 44 bytes. Φτάσαμε εδώ από 197 byte σε έξι επαναλήψεις. Αυτό είναι χοντρό Μείωση μεγέθους 77.7%.!
Αναρωτιέμαι όμως… είναι όντως αυτό το μικρότερο δυνατό μέγεθος; Έχουμε εξετάσει όλους τους πιθανούς τρόπους βελτιστοποίησης των μοτίβων SVG;
Σας προσκαλώ να δοκιμάσετε να ελαχιστοποιήσετε περαιτέρω αυτόν τον κώδικα ή ακόμα και να πειραματιστείτε με εναλλακτικές μεθόδους για τη βελτιστοποίηση των μοτίβων SVG. Θα ήθελα πολύ να δω αν θα μπορούσαμε να βρούμε το πραγματικό παγκόσμιο ελάχιστο με τη σοφία του πλήθους!
Περισσότερα για τη δημιουργία και τη βελτιστοποίηση μοτίβων SVG
Εάν ενδιαφέρεστε να μάθετε περισσότερα σχετικά με τη δημιουργία και τη βελτιστοποίηση μοτίβων SVG, διαβάστε το άρθρο μου σχετικά δημιουργία μοτίβων με φίλτρα SVG. Ή, αν θέλετε να δείτε μια συλλογή με 60+ μοτίβα, μπορείτε να δείτε το Συλλογή PetitePatterns CodePen. Τέλος, μπορείτε να παρακολουθήσετε τα σεμινάρια μου στο YouTube για να σας βοηθήσει να εμβαθύνετε στα μοτίβα SVG.
Βελτιστοποίηση των μοτίβων SVG στο μικρότερο μέγεθός τους δημοσιεύθηκε αρχικά στις CSS-Κόλπα. Θα έπρεπε λάβετε το ενημερωτικό δελτίο.
- "
- 10
- 100
- 77
- 9
- 98
- Σχετικά
- Απόλυτος
- Λογαριασμός
- Πρόσθετος
- Όλα
- Επιτρέποντας
- ήδη
- Άλλος
- πλησιάζω
- ΠΕΡΙΟΧΗ
- άρθρο
- γνωρίσματα
- διαθέσιμος
- ΑΞΟΝΕΣ
- Κομμάτι
- Μαύρη
- πρόκληση
- αλλαγή
- κλειστό
- κωδικός
- Κοινός
- σύνδεση
- Περιέχει
- περιεχόμενο
- συντεταγμένη
- θα μπορούσε να
- δημιουργία
- Ρεύμα
- ημερομηνία
- βαθύτερη
- κάτω
- τελειώνει
- εγκατεστημένος
- πάντα
- παράδειγμα
- Εκτός
- πείραμα
- Τελικά
- Όνομα
- ταιριάζουν
- ροή
- Βρέθηκαν
- περαιτέρω
- χάσμα
- να πάρει
- Παγκόσμιο
- που έχει
- ύψος
- βοήθεια
- εδώ
- Τόνισε
- Πως
- HTTPS
- προσδιορίσει
- εικόνα
- περιλαμβάνουν
- περιλαμβάνονται
- IT
- εαυτό
- γνωστός
- διαρροή
- ΜΑΘΑΊΝΩ
- μάθει
- μόχλευσης
- γραμμή
- λίγο
- κοίταξε
- αγάπη
- ΚΑΝΕΙ
- Κατασκευή
- διαχειρίζεται
- μαθηματικά
- νου
- περισσότερο
- πλέον
- μετακινήσετε
- MS
- αριθμός
- αριθμοί
- όφσετ
- Καλά
- ανοίξτε
- βελτιστοποιημένη
- αλλιώς
- πρότυπο
- φυσικός
- Σημείο
- τοποθετημένες
- δυνατός
- ισχυρός
- αρκετά
- τιμή
- διαδικασια μας
- παρέχει
- ποιότητα
- γύρος
- τρέξιμο
- Είπε
- αδιάλειπτη
- Σειρές
- σειρά
- σχήματα
- παρόμοιες
- Απλούς
- ΕΞΙ
- Μέγεθος
- So
- λύση
- κάτι
- Χώρος
- Spot
- Εκκίνηση
- ξεκινά
- υποστηριζόνται!
- ομιλία
- Μέσω
- κορυφή
- διαφανής
- tutorials
- χρήση
- αξία
- Δες
- W3
- Δες
- καλωσόρισμα
- Τι
- εντός
- χωρίς
- Εργασία
- εργαζόμενος
- λειτουργεί
- αξία
- YouTube