ColorMap example in CSS and Angular
Tempo di lettura: 5 minuti

Nel Utilizzo di un servizio angolare per leggere le variabili Sass tutorial abbiamo imparato come recuperare i colori del tema che sono definiti in un Sass .scss file utilizzando un servizio. L’associato applicazione demo pulsanti di opzione forniti per selezionare tra i colori del tema standard e una variazione più chiara o più scura. Ecco un esempio di come appariva.

Mentre l’articolo precedente descriveva come l’app caricava i colori dal Sass .scss file, questo illustrerà come memorizzare combinazioni di colori e variazioni per un facile accesso dal ColorService.

Mappatura delle proprietà del colore caricate su un tema specifico

Ricordiamo che il ColorService’s caricaColori() Il metodo ha semplicemente caricato ogni colore del tema in una mappa come coppia nome/valore CSS:

Esempio di ColorMap in CSS e Angular

Da lì, potremmo semplicemente memorizzare ciascuno di questi in una variabile come colore di sfondo, colore del bordo, ecc. Il problema è che il numero di variabili richieste cresce esponenzialmente con ogni variazione richiesta. Ad esempio, se avessimo solo un’opzione chiaro e scuro, ora avremmo bisogno di tre variabili per ogni proprietà: una per la proprietà e una per ogni stato. Un’idea migliore potrebbe essere quella di aggiornare semplicemente il Tasti mappa per accettare una combinazione proprietà+opzione. Dopo aver eseguito il processo di lettura delle proprietà CSS nell’ultimo articolo, facciamo il refactoring del caricaColori() codice per trasformare le proprietà CSS in un formato chiave più utile.

Leggi: Introduzione a TypeScript e alle sue caratteristiche

Iterando su Enums con TypeScript

Le enumerazioni non sono supportate da JavaScript vanilla, quindi, dietro le quinte, le enumerazioni TypeScript vengono trasposte in array associativi:

//in TypeScript
export enum PropertyNames {
  background  = 'background',
  hover="hover",
  focusborder="focus-border"
}

export enum ColorOptions {
  standard = '',
  light="light",
  dark     = 'dark'
}

//transpiled JavaScript
var PropertyNames;
(function (PropertyNames) {
    PropertyNames["background"] = "background";
    PropertyNames["hover"] = "hover";
    PropertyNames["focusborder"] = "focus-border";
})(PropertyNames = exports.PropertyNames || (exports.PropertyNames = {}));

var ColorOptions;
(function (ColorOptions) {
    ColorOptions["standard"] = "";
    ColorOptions["light"] = "light";
    ColorOptions["dark"] = "dark";
})(ColorOptions = exports.ColorOptions || (exports.ColorOptions = {}));

In quanto tale, possiamo ottenere chiavi e valori di enumerazioni usando il ES2017 Chiavi.oggetto() e Object.values() metodin per utilizzarli; dovremo configurare la libreria TypeScript per ES2017 o successivamente impostando il –lib opzione del compilatore. Ad esempio, usando tsconfig.json:

"compilerOptions": {
    "lib": ["es2017", "dom"]
}

Ora possiamo iterare su Nomi proprietà e associare Opzioni colore con ogni:

@Injectable()
export class ColorService {
  private _colorMap: Map<string, string> = new Map();
  
public loadColors() {
  // Read the custom property of body section with given name:
  const appElement = 
    document.getElementsByClassName('color-demo-app');
  if (appElement && appElement.length > 0) {
    const appStyles = window.getComputedStyle(appElement[0]);
    Object.values(PropertyNames).forEach(propertyName => {
      Object.values(ColorOptions).forEach(colorOption => {
        //...
      });
    });
  }
}

Dentro il nido per ciascuno() loop, possiamo assemblare il nome della variabile CSS da una combinazione di costanti e valori enum. Produce un potenziale nome di variabile CSS come “–dark-hover-color” o “–focus-border-color”:

Object.values(PropertyNames).forEach(propertyName => {
  Object.values(ColorOptions).forEach(colorOption => {
    const cssVariableName = CSS_PREFIX
      + (colorOption 
        ? `${colorOption}${CSS_DELIMITER}` 
        : '')
      + `${propertyName}${CSS_DELIMITER}`
      + CSS_SUFFIX;
  });
});


Ho detto “potenziale” perché in realtà non abbiamo definito tutte le possibili opzioni di colore per ogni nome di proprietà. Ecco tutti i colori del tema contenuti nel app.component.css file:

.color-demo-app {
  --background-color: #{$backgroundColor};
  --light-background-color: #{$lightBackgroundCcolor};
  --hover-color: #{$hoverColor};
  --dark-hover-color: #{$darkHoverColor};
  --focus-border-color: #{$focusBorderColor};
  --dark-focus-border-color: #{$darkFocusBorderColor};
}

Quindi il CSSStyleDeclaration’s getPropertyValue() Il metodo potrebbe risultare vuoto per alcuni nomi di variabili CSS, ad esempio “–dark-background-color”. In tal caso, il cssVariableValue sotto conterrebbe una stringa vuota (“), che possiamo controllare per l’utilizzo di JavaScript falsità test:

interface ColorProperty {
  name: PropertyNames,
  option: ColorOptions
} 

//inside the class
const cssVariableValue = 
  appStyles.getPropertyValue(cssVariableName)
           .replace(' ', '');
if (cssVariableValue) {
  const colorMapKey = <ColorProperty>{
    name: propertyName,
    option: colorOption
  };
  this._colorMap.set(
    JSON.stringify(colorMapKey),
    cssVariableValue
  );
}

Leggi: Scelta tra valori letterali ed enumerazioni di stringhe TypeScript

Utilizzo di oggetti come chiavi della mappa

Vorremmo memorizzare i valori delle variabili CSS ottenuti nel _colorMap utilizzando una chiave oggetto che combina il nome della proprietà e l’opzione del colore. Il problema è che gli oggetti non funzionano sempre come Tasti mappa! Ciò è dovuto al === test di uguaglianza che si comporta in modo diverso per gli oggetti rispetto ai tipi semplici come stringhe e numeri. Nel caso di oggetti, === restituisce true solo se entrambi gli oggetti sono la stessa cosa! Poiché ricreiamo la chiave ogni volta che recuperiamo un valore di colore, una chiave oggetto non funzionerà. In tali casi, una soluzione alternativa popolare è quella di eseguire il marshalling dell’oggetto in forma di stringa utilizzando JSON.stringify(). Ci vuole un oggetto come questo:

{
 name: "hover",
 option: "light"
}

e lo trasforma in questo:

"{"name":"hover","option":""}"

Ora possiamo aggiungere una voce al _colorMap come segue:

const colorMapKey = <ColorProperty>{
  name: propertyName,
  option: colorOption
};
this._colorMap.set(
  JSON.stringify(colorMapKey),
  cssVariableValue
);

Impostazione dei valori predefiniti del tema

Dopo aver caricato tutti i colori definiti e le relative opzioni associate, il _colorMap ora contiene sei voci:

"{"name":"background","option":""}" : "#52acf0"

"{"name":"background","option":"light"}" : "#9dd0f7"

"{"name":"hover","option":""}" : "blue"

"{"name":"hover","option":"dark"}" : "#000099"

"{"name":"focus-border","option":""}" : "darkgray"

"{"name":"focus-border","option":"dark"}" : "#434343"

Questi rappresentano tutte le possibili combinazioni colore+opzione. Tutto ciò che resta da fare è definire i colori del tema che stiamo effettivamente utilizzando. Per farlo, introdurremo un nuovo _mappa tematica che contiene solo il nome della proprietà come chiave, insieme al colore attivo. Nel setThemeDefaults() metodo (chiamato alla fine di caricaColori()), inizieremo con i colori standard:

private _themeMap: Map<string, string> = new Map();

public get themeMap() {
  return this._themeMap;
}
  
private setThemeDefaults() { 
  Object.values(PropertyNames).forEach(propertyName => {
    const color = 
      this._colorMap.get(JSON.stringify(<ColorProperty>{
        name: propertyName,
        option: ColorOptions.standard
      }));
    this._themeMap.set(propertyName, color);
  });
}

Questo ci dà i seguenti colori del tema che vediamo quando l’app viene caricata per la prima volta:

background : "#52acf0"

hover : "blue"

"focus-border" : "darkgray"

Applicazione delle opzioni di colore in Angular

L’evento di modifica dei pulsanti di opzione è legato a setColor() metodo del Componente dell’app. Imposta il nome della proprietà e la combinazione di opzioni di colore e inoltra la richiesta al metodo di servizio colore con lo stesso nome:

public setColor(
  name: PropertyNames, 
  option: ColorOptions = ColorOptions.standard
) {
  this.colorService.setColor({
    name: name,
    option: option
  })
}

Il metodo di servizio recupera la voce dal _colorMap e aggiorna il _mappa tematica con il nuovo colore:

public setColor(colorProperty: ColorProperty) {
  const colorProps = JSON.stringify(colorProperty);
  const themeColor = this._colorMap.get(colorProps);
  this._themeMap.set(colorProperty.name, themeColor);
}

C’è una demo con il codice di oggi attivo stackblitz.

Conclusione sulla gestione dei colori dei temi in Angular

Nell’articolo di oggi abbiamo imparato a gestire i colori del tema utilizzando una combinazione di Mappa “Oggetto” e Mappa di stringhe (enum). La prima mappa memorizzava tutti i colori e le variazioni disponibili, mentre la seconda teneva traccia dei colori del tema corrente. Ho messo tutte le definizioni di colore e opzione nel ColorService, ma puoi scegliere di ospitarli nel Componente dell’app e passali al servizio se vuoi che sia più agnostico. La tua applicazione potrebbe anche recuperare le definizioni dei colori da un’altra fonte. Le permutazioni sono davvero infinite.

Leggi: Dieci modi per utilizzare Angular JS

Source link

Di Simone Serra

Web Designer Freelancer Realizzazione Siti Web Serra Simone Realizzo siti web, portali ed e-commerce con focus specifici sull’usabilità, l’impatto grafico, una facile gestione e soprattutto in grado di produrre conversioni visitatore-cliente. Elaboro siti internet, seguendo gli standard Web garantendo la massima compatibilità con tutti i devices. Sviluppo e-commerce personalizzati, multilingua, geolocalizzati per potervi mettere nelle migliori condizioni di vendita. Posiziono il tuo sito su Google per dare maggiore visibilità alla tua attività sui motori di ricerca con SEO di base o avanzato.