Κατάδυση σε JavaScript: Πώς να δημιουργήσετε ένα Hex2RGB Color Converter

Ενημέρωση (23/07/2019): Έχω διορθώσει ορισμένα γραμματικά σφάλματα και άλλαξα λίγο τον κώδικα app.js καταργώντας τη λειτουργία checkBG.

Σε αυτό το άρθρο, θα δημιουργήσουμε μια εφαρμογή ιστού που μετατρέπει κωδικούς χρώματος μεταξύ δεκαεξαδικής φόρμας και φόρμας RGB.

Μπορείτε να βρείτε μια επίδειξη εδώ και τον πηγαίο κώδικα εδώ.

Δομή έργου:

Η δομή του έργου είναι πολύ απλή.

  1. index.html : Περιέχει τη δομή της εφαρμογής.
  2. style.css : Στυλ της σελίδας.
  3. app.js : Περιέχει όλο τον μαγικό κώδικα.

Ιδέα:

Ακολουθεί η λίστα με τα πράγματα που ήθελα να εκτελέσει αυτή η εφαρμογή:

  1. Κάθε φορά που κάτι πληκτρολογείται σε πεδίο κειμένου για hex, η εφαρμογή θα πρέπει να ελέγχει αν το χρώμα είναι έγκυρο. Εάν είναι, μετατρέψτε το σε RGB, ορίστε το ως φόντο και, στη συνέχεια, τοποθετήστε την τιμή RGB στο πεδίο κειμένου RGB και αντίστροφα.
  2. Εάν ένας σύντομος εξαγωνικός κωδικός χρώματος πληκτρολογείται στο πεδίο κειμένου, αναπτύξτε τον όταν το πεδίο κειμένου χάσει την εστίαση (ο χρήστης κάνει κλικ εκτός της περιοχής κειμένου).
  3. Προσθέστε αυτόματα το σύμβολο # # στην εξάγωνη είσοδο.

Ας ξεκινήσουμε!

index.html

      Hex to RGB Converter HEX <--> RGB 

Δημιουργήσαμε δύο πεδία κειμένου με αναγνωριστικό "hex" και "rgb" αντίστοιχα. Δίπλα σε κάθε είσοδο υπάρχει ένα εικονίδιο SVG για σφάλμα, το οποίο έχει μια κατηγορία κρυφών, από προεπιλογή.

style.css

:root { --color: rgba(255,255,255,0.9); --tweet: white; } * { margin: 0; padding: 0; box-sizing: border-box; } ::placeholder { color: var(--color)!important; } body { padding: 50px; width: 100vw; height: 100vh; display: flex; align-items: center; justify-content: center; background-color: #28a745; font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; } .head { position: absolute; top: 30px; text-align: center; color: var(--tweet); font-size: 3rem; border-bottom: 2px solid var(--tweet); } #content { display: block; } input { color: var(--color)!important; margin: 1rem 0; width: 400px; border: none; border-bottom: 1px solid var(--color); font-size: 2.5rem; background-color: transparent; } input:focus { outline: none; } img { width: 24px; } .hidden { visibility: hidden; opacity: 0.8; } .dark { --color: rgba(0,0,0,0.75); --tweet: rgba(0,0,0,0.95); } @media only screen and (max-width: 560px){ #content input { margin: 0.75rem 0; width: 90%; font-size: 1.875rem; } #content img { width: 16px; } .head { font-size: 2rem; } } 

Εδώ είναι μια βασική διάταξη για να κάνετε τη σήμανση να φαίνεται λίγο καλύτερη. Έχουμε ορίσει δύο τάξεις εδώ, .hiddenκαι .dark..hiddenχρησιμοποιείται για την απόκρυψη / εμφάνιση του εικονιδίου σφάλματος SVG και .darkγια την αλλαγή του χρώματος κειμένου με βάση το χρώμα του φόντου. Από προεπιλογή, έχω ορίσει το κείμενο σε σκούρο χρώμα (για φωτεινό φόντο).

app.js

Εδώ είναι το μαγικό μέρος. Θα χωρίσω τον κώδικα σε κομμάτια:

Πρώτον, έχουμε ορίσει μεταβλητές που στοχεύουν τις εισόδους με id «hex» και «rgb». Στη συνέχεια, έχουμε λειτουργίες για να ελέγξουμε εάν η είσοδος Hex / RGB είναι έγκυρη ή όχι. Χρησιμοποιούν μια βασική ρύθμιση regex και επιστρέφουν ένα boolean. Εάν σας εκφοβίζονται, σας προτείνω να δοκιμάσετε αυτό το RegexTutorial.

Εδώ, γράψαμε μια συνάρτηση ανάλυσης που ονομάζεται modifyHexπου ελέγχει εάν το εξάγωνο εισόδου έχει μήκος 4 χαρακτήρων. Δηλαδή, περιέχει το "#" και είναι στενό (για παράδειγμα, # 333) και αντικαθιστά το "#" με έναν κενό χαρακτήρα. Στη συνέχεια, ελέγχει εάν το μήκος είναι τώρα 3 και το επεκτείνει σε 6 χαρακτήρες (για παράδειγμα, # 123 = # 112233).

Έχουμε ορίσει δύο συναρτήσεις που μετατρέπουν το hex σε rgb και το αντίστροφο. Ακολουθεί μια αναλυτική ανάλυση για hexToRgb(Αυτή η διαδικασία γράφεται σε εκτεταμένη μορφή για καλύτερη κατανόηση):

  1. Ορίστε έναν κενό πίνακα για να αποθηκεύσετε το αποτέλεσμα.
  2. Αντικαταστήστε το σύμβολο "#", εάν υπάρχει και εάν το μήκος δεν είναι ίσο με 6 (δηλαδή, η σύντομη έκδοση), καλέστε την παραπάνω modifyHexσυνάρτηση και αναπτύξτε την.
  3. Με έναν πολύ βασικό τρόπο, το hex to rgb λειτουργεί μετατρέποντας τον hex κώδικα (στη βάση 16) σε rgb code (στη βάση 10). Κάθε δύο χαρακτήρες στον δεκαεξαδικό κώδικα αντιπροσωπεύουν μια τιμή στον κωδικό χρώματος rgb. Για παράδειγμα στο #aabbcc, το κόκκινο είναι (aa στη βάση 10), το πράσινο είναι (bb στη βάση 10) και το μπλε είναι (cc στη βάση 10). Έτσι, στη συνάρτηση, κόβουμε την εξάγωνη τιμή, τη μετατρέπουμε σε βάση 10 χρησιμοποιώντας parseIntκαι στη συνέχεια αποθηκεύουμε την στον καθορισμένο πίνακα.
  4. Τέλος, επιστρέφουμε τη συμβολοσειρά εξόδου συνδέοντας τον παραπάνω πίνακα.

Για τη rgbToHexσυνάρτηση (αυτό γράφεται με μικρότερη λογική):

  1. Χρησιμοποιούμε άμεσα ένα regex για να εξαγάγουμε μόνο τις τιμές αριθμών - δηλαδή, το rgb (123,21,24) θα επιστρέψει 123,21,24.
  2. Στη συνέχεια, χρησιμοποιούμε μια λειτουργία χάρτη για να επιστρέψουμε έναν νέο πίνακα, ο οποίος μετατρέπει τον αριθμό σε βάση 16 και, στη συνέχεια, συμπληρώνει την τιμή.

Το regex που χρησιμοποιήσαμε παραπάνω επιστρέφει δεδομένα τύπου «string». Για να το μετατρέψουμε σε Βάση 16, πρέπει να χρησιμοποιήσουμε τη toString()  μέθοδο, με μια παράμετρο «16».

Τώρα, η toString()μέθοδος εφαρμόζεται μόνο σε αριθμητικούς τύπους δεδομένων, επομένως χρησιμοποιούμε parseIntγια να μετατρέψουμε πρώτα κάθε στοιχείο του πίνακα σε έναν αριθμό, στη συνέχεια να το χρησιμοποιήσουμε toString(16)για να το μετατρέψουμε σε δεκαεξαδική μορφή και, στη συνέχεια, να προσθέσουμε επιθέματα ώστε να έχει μήκος 2 χαρακτήρων. Η επένδυση είναι απαραίτητη, εάν έχετε κάτι σαν «14», το οποίο θέλετε να μετατρέψετε σε δεκαεξαδικό, θα επιστρέψει «e». Όμως, ο δεκαεξαδικός κωδικός χρώματος χρειάζεται 2 χαρακτήρες για κάθε μέρος, οπότε απαιτείται παραγέμισμα, γεγονός που το καθιστά «0e».

Σημείωση: padStartείναι μια δυνατότητα ES8, η οποία ενδέχεται να μην υποστηρίζεται σε κάθε πρόγραμμα περιήγησης. Για να διατηρήσω αυτό το σεμινάριο απλό, δεν το έχω μεταδώσει στο ES5.

3. Τέλος, επιστρέφουμε τον προκύπτοντα πίνακα, ενώνοντας τον και μετατρέποντάς τον σε κεφαλαία.

errorMark()Η λειτουργία χρησιμοποιείται για την εμφάνιση ή απόκρυψη του εικονιδίου σφάλματος SVG. Περνά απλώς τα περιεχόμενα της εισόδου ( hex.valueκαι rgb.value) μέσω των αντίστοιχων λειτουργιών ελέγχου και χρησιμοποιεί το boolean που επιστρέφει για προσθήκη / αφαίρεση της .hiddenκλάσης.

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

Προσθήκη ακροατών συμβάντων:

Τέλος, συνδέουμε όλες τις λειτουργίες προσθέτοντας Event Listeners.

Πρώτον, προσθέτουμε ένα keyupσυμβάν στην hexείσοδο. Αυτό το συμβάν ενεργοποιείται κάθε φορά που απελευθερώνεται ένα κλειδί. Ακολουθεί η ανάλυση της διαδικασίας:

  1. Ελέγξτε εάν ο κωδικός εισαγωγής είναι έγκυρος και αναπτύξτε τον εάν είναι στενός.
  2. Ρυθμίστε το χρώμα φόντου του σώματος στην τιμή εισαγωγής.
  3. Ελέγξτε την αντίθεση χρώματος και αλλάξτε ανάλογα το χρώμα του κειμένου.
  4. Καλέστε τη λειτουργία μετατροπής και τοποθετήστε το μετατρεπόμενο χρώμα στο πεδίο εισαγωγής RGB.

Ο άλλος ακροατής συμβάντων που χρησιμοποιήσαμε είναι blur. Ενεργοποιείται κάθε φορά που η είσοδος χάνει «εστίαση», ή με απλούς όρους, κάθε φορά που κάνετε κλικ / πατάτε έξω από το στοιχείο εισόδου, blurενεργοποιείται. Επομένως, είναι καλό να τροποποιήσετε το εξάγωνο εισόδου!

So, we check if the hex color is valid or not, then we expand it if it is short, and finally we add a ‘#’ if it doesn’t exist. Note that we are checking if index 0 and 1 contain ‘#’. This is done so that the function doesn’t prepend ‘#’ twice.

The same keyup event listener is added to the RGB input and it too follows the same series of steps as the hex event listener.

Lastly, we have added an event listener keyup to the entire document, that is, it will be triggered for any of the two input elements. In it, we are calling the errorMark function, which adds the error icon, in case there’s an error, or removes it if everything is valid.

Here’s the final code for app.js :

const hex = document.getElementById("hex"); const rgb = document.getElementById("rgb"); // Check Functions function checkHex(hex) { const hexRegex = /^[#]*([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/i if (hexRegex.test(hex)) { return true; } } function checkRgb(rgb) { const rgbRegex = /([R][G][B][A]?[(]\s*([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\s*,\s*([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\s*,\s*([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])(\s*,\s*((0\.[0-9]{1})|(1\.0)|(1)))?[)])/i if (rgbRegex.test(rgb)) { return true } } // Parse Function function modifyHex(hex) { if (hex.length == 4) { hex = hex.replace('#', ''); } if (hex.length == 3) { hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2]; } return hex; } // Converting Functions function hexToRgb(hex) { let x = []; hex = hex.replace('#', '') if (hex.length != 6) { hex = modifyHex(hex) } x.push(parseInt(hex.slice(0, 2), 16)) x.push(parseInt(hex.slice(2, 4), 16)) x.push(parseInt(hex.slice(4, 6), 16)) return "rgb(" + x.toString() + ")" } function rgbToHex(rgb) { let y = rgb.match(/\d+/g).map(function(x) { return parseInt(x).toString(16).padStart(2, '0') }); return y.join('').toUpperCase() } // Helper Functions function addPound(x) { return '#' + x; } // Function to add cross mark on error values function errorMark() { if (checkHex(hex.value)) { document.getElementById('hexError').classList.add('hidden'); } else { document.getElementById('hexError').classList.remove('hidden'); } if (checkRgb(rgb.value)) { document.getElementById('rgbError').classList.add('hidden'); } else { document.getElementById('rgbError').classList.remove('hidden'); } } // Finding Contrast Ratio to change text color. Thanks //stackoverflow.com/a/11868398/10796932 function getContrastYIQ(hexcolor) { if (checkHex(hexcolor)) { hexcolor = hexcolor.replace("#", '') } else { hexcolor = rgbToHex(hexcolor) } var r = parseInt(hexcolor.substr(0, 2), 16); var g = parseInt(hexcolor.substr(2, 2), 16); var b = parseInt(hexcolor.substr(4, 2), 16); var yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000; return (yiq >= 128) ? document.body.classList.add('dark') : document.body.classList.remove('dark') } // Adding Event Listeners hex.addEventListener('keyup', function() { let color = hex.value if (checkHex(color)) { color = modifyHex(color); document.body.style.backgroundColor = addPound(color); getContrastYIQ(color) rgb.value = hexToRgb(color); } }) hex.addEventListener('blur', function() { if (checkHex(hex.value)) { hex.value = modifyHex(hex.value) if (hex.value[1] != '#') { if (hex.value[0] != '#') { hex.value = addPound(hex.value); } } } }) rgb.addEventListener('keyup', function() { let color = rgb.value if (checkRgb(color)) { hex.value = color = addPound(rgbToHex(color)) document.body.style.backgroundColor = color; getContrastYIQ(color) } }) document.addEventListener('keyup', function() { errorMark(); })

Conclusion

Ορίστε! Ξέρω ότι ο κώδικας δεν είναι τέλειος και μπορεί να αναδιαμορφωθεί, αλλά hei, αυτή είναι μόνο η αρχή. Αν θέλετε να βελτιώσετε αυτόν τον κώδικα, μπορείτε να προχωρήσετε και να ανοίξετε ένα PR στο github repo μου.

Καλή κωδικοποίηση!