Πώς να δημιουργήσετε ένα προσαρμοσμένο θέμα στο γωνιακό υλικό

Το Angular Material είναι μια εξαιρετική βιβλιοθήκη που εφαρμόζει το Material Design για Angular 2+. Το επίσημο έγγραφο αρκεί για τις χρήσεις των στοιχείων, ενώ υπάρχουν λίγα άρθρα σχετικά με τον τρόπο προσαρμογής του ίδιου του θέματος, συγκεκριμένα, των χρωμάτων που χρησιμοποιούνται στο θέμα.

Σε αυτήν την ανάρτηση, θα ήθελα να συνοψίσω όσα έχω μάθει αυτούς τους μήνες από την προσαρμογή θεμάτων γωνιακού υλικού.

Σημειώστε ότι αυτό το άρθρο ΔΕΝ αφορά το υλικό AngularJS, το οποίο χρησιμοποιείται για το AngularJS 1.x.

σχετικές αναρτήσεις

Μερικές κοινές αναρτήσεις σχετικά με την προσαρμογή θεμάτων είναι:

  • "Theming your Angular Material app", ο επίσημος οδηγός για προσαρμοσμένα θέματα,
  • «Ο πλήρης οδηγός για θέματα γωνιακού υλικού» του Tomas Trajan, ο οποίος παρέχει πολλές οδηγίες χωρίς έγγραφα. Συνιστάται ανεπιφύλακτα .

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

Πώς να δημιουργήσετε ένα προσαρμοσμένο θέμα

Η δημιουργία ενός θέματος υλικού είναι εξαιρετικά απλή: πρέπει να επιλέξετε μόνο τρία χρώματα - πρωτεύουσα , προφορά και προειδοποίηση - και το γωνιακό υλικό θα κάνει τα υπόλοιπα για εσάς. Η σελίδα παλέτας υλικού εξηγεί πώς λειτουργεί καθαρά και μπορείτε επίσης να δημιουργήσετε ένα θέμα οπτικά με το Color Tool.

Όσον αφορά τον κώδικα, το μόνο που χρειάζεται να κάνετε είναι να δημιουργήσετε το ακόλουθο αρχείο θέματος:

// [email protected] '[email protected]/material/theming';
$my-theme-primary: mat-palette($mat-green);$my-theme-accent : mat-palette($mat-amber);$my-theme-warn : mat-palette($mat-red);
$my-theme: mat-light-theme( $my-theme-primary, $my-theme-accent, $my-theme-warn);

Στη συνέχεια, πρέπει να εφαρμόσετε αυτό το θέμα στο κύριο style.scssαρχείο σας:

@import "theme.scss";
@include mat-core();@include angular-material-theme($my-theme);

Τρόπος χρήσης προσαρμοσμένου θέματος σε στοιχεία

Αφού δημιουργήσουμε το δικό μας θέμα, θα αυξηθούν απαιτήσεις όπως αυτό:

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

Αυτή η απαίτηση είναι πολύ συνηθισμένη - ούτως ή άλλως, η δυνατότητα χρήσης σε στοιχεία είναι ακριβώς ο λόγος που θέλουμε να δημιουργήσουμε ένα προσαρμοσμένο θέμα. Το πρόβλημα είναι πώς.

Η προσέγγιση mixin

Το πρώτο επίσημο έγγραφο που μοιράστηκα πρότεινε έναν τρόπο χρήσης του SCSS mixin. Το ονομάζω προσέγγιση «από κάτω προς τα πάνω», η οποία περιλαμβάνει τα ακόλουθα βήματα:

  1. Κάθε στοιχείο καθορίζει ένα μείγμα θέματος και ανακτά χρώματα από την $themeπαράμετρο.
  2. Ένα καθολικό theme.scssκαθορίζει το προσαρμοσμένο θέμα και, στη συνέχεια, περιλαμβάνει όλα τα συνδυαστικά θέματα και τα καλεί με το προσαρμοσμένο θέμα.

Εκτός από τον theme.scssορισμό που αναφέρθηκε παραπάνω, κάθε στοιχείο πρέπει να δημιουργήσει ένα αρχείο θέματος όπως αυτό:

// src/app/comp-a/[email protected] '[email protected]/material/theming';
@mixin comp-a-theme($theme) { // define mixin $primary: map-get($theme, primary); // retrieve color def button { // apply theme to component background-color: mat-color($primary); }}

Και μάλλον θέλετε custom-theme.scssνα εισαγάγετε όλα τα θέματα επιπέδου στοιχείων:

// src/app/[email protected] '[email protected]/material/theming';@import 'src/app/comp-a/comp-a.theme';@import 'src/app/comp-b/comp-b.theme';
@mixin custom-themes($theme) { @include comp-a-theme($theme); @include comp-b-theme($theme);}

Στη συνέχεια, εισαγάγετε τα παραπάνω custom-theme.scssστο theme.scss:

// [email protected] './custom-theme';@include custom-themes($my-theme);

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

Ωστόσο, τις περισσότερες φορές υποστηρίζουμε μόνο ένα θέμα και η χρήση ενός συνδυασμού θα μπορούσε να είναι δυσκίνητη. Κυρίως υπάρχουν τρία μειονεκτήματα με αυτήν την προσέγγιση:

  1. Κάθε αναφορά χρώματος χρειάζεται ξεχωριστό .theme.scssαρχείο.
  2. custom-theme.scssπρέπει να γνωρίζει ακριβώς ποια στοιχεία παρέχουν προσαρμοσμένα θέματα. Αυτό δημιουργεί περιττές εξαρτήσεις.
  3. Το πιο σημαντικό, τα αρχεία θέματος επιπέδου συστατικών δεν είναι ενθυλακωμένα.

Το πρώτο και το δεύτερο σημείο είναι αρκετά αυτονόητα. Επιτρέψτε μου να εξηγήσω λίγο για το σημείο 3. Αυτό περιλαμβάνει κάποιες βασικές γνώσεις που ονομάζονται "View Encapsulation".

Η Angular χρησιμοποιεί μια τεχνική που ονομάζεται "View Encapsulation" για να διατηρεί το στοιχείο CSS τοπικό. Με άλλα λόγια, οι κανόνες που ορίζονται για ένα στοιχείο θα παραμείνουν σε αυτό το στοιχείο και δεν θα επηρεάσουν άλλα στοιχεία.

Με αυτόν τον τρόπο μπορείτε να ορίσετε ελεύθερα το όνομα της κλάσης CSS στο στοιχείο σας χωρίς να ανησυχείτε για ονομασίες διενέξεων. Ωστόσο, η ενθυλάκωση προβολής γίνεται μόνο εάν το CSS ορίζεται μέσω @Component, δηλαδή @Component({ styleUrls: ['./comp-a.scss'] }).

Όσον αφορά το προσαρμοσμένο αρχείο θέματος comp-a.theme.scss, καθώς εισάγεται απευθείας από custom-theme.scss, οι κανόνες του δεν είναι ενσωματωμένοι, οπότε θα ισχύει για όλα τα στοιχεία της σελίδας. Στο παραπάνω παράδειγμα, χρησιμοποίησα τον ακόλουθο κώδικα (που ήταν ΛΑΘΟΣ!):

@mixin comp-a-theme($theme) { button { ... } // This will apply to ALL buttons!}

Αλλά αυτό θα εφαρμόσει το στυλ σε όλα τα κουμπιά αντί για εκείνα τα κουμπιά που ανήκουν comp-aμόνο. Πρέπει να κάνετε κάτι σαν comp-a buttonνα κάνετε αυτό το έργο σωστά.

Η άμεση προσέγγιση

Γι 'αυτό προτείνω μια καλύτερη προσέγγιση. Αντί να χρησιμοποιούμε μια μίξη, αφήνουμε σε κάθε στοιχείο να περιλαμβάνει το αρχείο θέματος και να χρησιμοποιούμε απευθείας τον ορισμό χρώματος.

Σε αυτήν την προσέγγιση, το αρχείο θεματικού στοιχείου θα έχει την εξής μορφή:

// NOTE: just do this in your regular scss file.// No need to create separate theme file!// src/app/comp-a/[email protected] 'src/theme.scss';
$primary: map-get($my-theme, primary);button { background-color: mat-color($primary);}

Και αυτό είναι όλο.

Let’s see how this works. First, theme related rules are put into the component SCSS file, so no extra component level theme file required. Second, the main theme.scss does not need to know component level themes (since it does not need to import them), so a simple theme definition is adequate. Third, the component SCSS file is used with @Component so it is encapsulated correctly, which means we can simply define rules for button.

Predefined Theme Keys

Probably you have noticed the next problem. What are the foreground, primary in above theme files ( map-get($my-theme, primary))? Are there any other keys I can use?

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

Ανοίξτε node_modules/@angular/material/_theming.scssκαι θα δείτε τους ορισμούς για αυτά τα πλήκτρα. Για μελλοντική αναφορά, θα ήθελα να συνοψίσω τα κλειδιά εδώ.

$theme |- primary |- accent |- warn |- foreground | |- base | |- divider | |- dividers | |- disabled | |- disabled-button | |- disabled-text | |- hint-text | |- secondary-text | |- icon | |- icons | |- text | |- slider-min | |- slider-off | `- slider-off-active |- background | |- status-bar | |- app-bar | |- background | |- hover | |- card | |- dialog | |- disabled-button | |- raised-button | |- focused-button | |- selected-button | |- selected-disabled-button | |- disabled-button-toggle | |- unselected-chip | `- disabled-list-option `- is-dark // bool, whether dark theme or not

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

$foreground: map-get($my-theme, foreground);.disabled-text { color: mat-color($foreground, disabled-text);}

Εντάξει, αυτά είναι μερικά μαθήματα που έχω μάθει από την πάλη με το Angular Material. Ελπίζω αυτή η ανάρτηση να είναι χρήσιμη αν αντιμετωπίζετε παρόμοια προβλήματα.