Saltar al contenido

Obtenga el esquema / paleta de colores del tema Material 2 para otros elementos

Luego de mucho luchar hemos hallado el arreglo de este dilema que muchos los usuarios de nuestro espacio han tenido. Si quieres aportar alguna información no dejes de compartir tu conocimiento.

Solución:

¡Encontré una solución increíble! Estoy muy emocionado de mostrar esto porque me ha estado molestando sobre cómo implementarlo durante años. Así que aquí va; Primero, cambie todos sus archivos css a scss;

Para proyectos existentes

  • Ejecutar en consola ng set defaults.styleExt=scss

(ng set parece haberse depreciado, pero puede consultar esto para obtener una solución gracias al usuario @wlyles get / set han quedado obsoletos en favor del comando config)

  • Cambiar el nombre de todos los existentes .css archivos a .scss
  • Cambie manualmente la extensión del archivo de styles en .angular-cli.json de .css a .scss
  • Si no utilizó una herramienta como WebStorm Refactor para cambiar el nombre, cambie manualmente todos los styleUrls de .css para .scss

Para proyectos futuros

  • Solo para su nuevo proyecto, simplemente use ng new your-project-name --style=scss

  • Para que todos los proyectos nuevos utilicen scss use ng set defaults.styleExt=scss --global

Ahora necesitará tener un archivo theme.scss en la raíz de su aplicación así:
donde están los temas

Ahora, en su archivo style.scss, desea agregar lo siguiente (como puede ver, hago referencia al color de fondo, pero puede cambiar esto a cualquier elemento del tema de su sitio como desee):

EDITAR: NO NECESITA poner este elemento @mixin personalizado en su styles.scss puedes ponerlo en cualquiera de tus *name*.component.scss y luego simplemente impórtelo e inclúyalo de la misma manera que lo hace con el ejemplo dado.

@import '[email protected]
/material/theming'; // Define a custom mixin that takes in the current theme @mixin theme-color-grabber($theme) // Parse the theme and create variables for each color in the pallete $primary: map-get($theme, primary); $accent: map-get($theme, accent); $warn: map-get($theme, warn); // Create theme specfic styles .primaryColorBG background-color: mat-color($primary); .accentColorBG background-color: mat-color($accent); .warnColorBG background-color: mat-color($warn);

Ahora ve a tu archivo theme.scss que usas para tematizar tus elementos de Material 2, si necesitas ayuda con la tematización, mira esto: Material 2 Github – Guía de temática

Ahora abra su theme.scss e importe su style.scss, ya que mi theme.scss está dentro de la raíz del /src/app/theme.scss carpeta, primero debo salir de ella para hacer referencia a mi /src/styles.scss archivo de estilo global como tal;

@import '../styles';

Entonces debemos incluir nuestra nueva costumbre @mixin creamos en TODOS nuestros temas (si tiene varios como yo, por lo que cambia de color de acuerdo con el tema seleccionado actual).

Inclúyalo sobre el tema de material angular real, así:

@include theme-color-grabber($theme);
@include angular-material-theme($theme);

Si tiene algún tema como yo, agréguelo en la misma posición, así:

.light 
  $light-primary: mat-palette($mat-blue, 200,300, 900);
  $light-accent:  mat-palette($mat-light-blue, 600, 100, 800);
  $light-warn:    mat-palette($mat-red, 600);
  $light-theme: mat-dark-theme($light-primary, $light-accent, $light-warn);
  @include theme-color-grabber($light-theme);
  @include angular-material-theme($light-theme);


Puedes ver que agregué mi theme-color-grabber por encima de la inclusión, realmente no importa si está por encima o por debajo del tema real porque está obteniendo los colores de los temas, que es el punto principal.

Todo mi themes.scss se ve así:

@import '[email protected]/material/theming';
//We import our custom scss component here
@import '../styles';

@include mat-core();

$theme-primary: mat-palette($mat-red);
$theme-accent:  mat-palette($mat-deep-orange, A200, A100, A400);
$theme-warn:    mat-palette($mat-red);
$theme: mat-dark-theme($theme-primary, $theme-accent, $theme-warn);
//
@include theme-color-grabber($theme);
@include angular-material-theme($theme);
.light 
  $light-primary: mat-palette($mat-blue, 200,300, 900);
  $light-accent:  mat-palette($mat-light-blue, 600, 100, 800);
  $light-warn:    mat-palette($mat-red, 600);
  $light-theme: mat-dark-theme($light-primary, $light-accent, $light-warn);
  @include theme-color-grabber($light-theme);
  @include angular-material-theme($light-theme);


¡Y finalmente ahora podemos recurrir al color de nuestros temas para un fondo EN CUALQUIER LUGAR !, por ejemplo, doy un mat-grid-tile el color ‘primario’ (no toma el argumento color = ”, como otros elementos como mat-toolbar) simplemente estableciendo su clase en el nombre de clase apropiado así:

EDITAR: En cada uno de los archivos scss de sus componentes, necesitará import '/theme.scss' para que su tema se aplique a ese componente. No importar theme.scss en styles.scss ¡porque eso creará un bucle de importación!


  
    

Callum

Tech

Ambitious and ready to take on the world of Information Technology,
my love for programming and all things I.T. has not wavered since I first got access
to my fathers computer at age 9.

¡Finalmente nuestro resultado se verá así !:

Tema rojo activoTema rojo

Tema azul activoingrese la descripción de la imagen aquí

Yo personalmente puse esos en variables css4 para poder usarlos sin importaciones como tal

background: var(--color-primary)

Y aquí se explica cómo configurar las variables css4

@import '[email protected]/material/theming';
// Include the common styles for Angular Material. We include this here so that you only
// have to load a single css file for Angular Material in your app.
// Be sure that you only ever include this mixin once!
@include mat-core();

// Define the palettes for your theme using the Material Design palettes available in palette.scss
// (imported above). For each palette, you can optionally specify a default, lighter, and darker
// hue. Available color palettes: https://material.io/design/color/
$app-primary: mat-palette($mat-blue);
$app-accent:  mat-palette($mat-orange);
$app-warn:    mat-palette($mat-red);
$app-success: mat-palette($mat-light-green);

// Create the theme object (a Sass map containing all of the palettes).
$app-theme: mat-light-theme($app-primary, $app-accent, $app-warn);

// Include theme styles for core and each component used in your app.
// Alternatively, you can import and @include the theme mixins for each component
// that you are using.
@include angular-material-theme($app-theme);

$primary: map-get($app-theme, primary);
$accent: map-get($app-theme, accent);

:root 
  --color-primary: #mat-color($app-primary);
  --color-accent: #mat-color($app-accent);
  --color-warn: #mat-color($app-warn);
  --color-success: #mat-color($app-success);

ahora los colores se pueden usar en archivos css sin importar con

background: var(--color-primary)

ACTUALIZAR:

Aquí se publicó una nueva versión de esta solución:

https://github.com/mirismaili/angular-material-dynamic-themes

Si solo necesita la respuesta a la pregunta formulada, probablemente sea mejor consultar la primera versión de la respuesta, a continuación. Además, recomiendo leer esta sección de la documentación del repositorio anterior: Use temas materiales para otros elementos.

Pero si desea otras capacidades que ve en el video a continuación, le recomiendo este nuevo enfoque.

Video

  • Demo en vivo:

    https://stackblitz.com/github/mirismaili/AngularMaterialDynamicThemes

Gracias, StackBlitz


RESPUESTA ARCHIVADA:

ingrese la descripción de la imagen aquí

stackblitz aquí


Partes más importantes:

En tus styles.scss (o themes.scss si usted tiene):

@import '[email protected]/material/theming';

@include mat-core();

@mixin define-css-classes($theme) 
    @include angular-material-theme($theme);

    $primary: map-get($theme, primary);
    $accent: map-get($theme, accent);
    $warn: map-get($theme, warn);
    $background: map-get($theme, background);
    $foreground: map-get($theme, foreground);

    // CSS THEME-DEPENDENT-STYLES ARE HERE:
    .theme-dependent-colors 
        background: mat-color($primary);
        color: mat-color($accent);
    


/**
* Define your custom themes in this map. 
* The `key` of each member is the name of CSS class for that theme. 
* To better understand the schema of the map, see `@each` loop below and especially pay attention to `map-has-key()` functions.
*/ 
$app-themes: (
        indigo-pink : (primary-base: $mat-indigo, accent-base: $mat-pink),
        deeppurple-amber: (primary-base: $mat-deep-purple, accent-base: $mat-amber),
        pink-bluegrey : (primary-base: $mat-pink, accent-base: $mat-blue-gray, is-dark: true),
        purple-green : (primary-base: $mat-purple, accent-base: $mat-green, is-dark: true),
);

@each $css-class, $theme in $app-themes 
    $primary: if(map-has-key($theme, primary), map-get($theme, primary), mat-palette(map-get($theme, primary-base)));

    $accent: if(map-has-key($theme, accent), map-get($theme, accent), mat-palette(map-get($theme, accent-base)));

    $warn: if(map-has-key($theme, warn), map-get($theme, warn), mat-palette(
            if(map-has-key($theme, warn-base), map-get($theme, warn-base), $mat-red)
    ));

    .#$css-class 
        @include define-css-classes(mat-light-theme($primary, $accent, $warn));
    

    .#$css-class-dark 
        @include define-css-classes(mat-dark-theme($primary, $accent, $warn));
    

    .theme-primary.#$css-class 
        background-color: mat-color($primary);
    

    ...


Cambio de tema dinámico, usando setTheme() en mecanografiado (ver aquí y aquí):

import Component, HostBinding from '@angular/core';
import OverlayContainer from "@angular/cdk/overlay";

const THEME_DARKNESS_SUFFIX = `-dark`;

export class AppComponent 
    @HostBinding('class') activeThemeCssClass: string;
    isThemeDark = false;
    activeTheme: string;

    setTheme(theme: string, darkness: boolean = null) 
        if (darkness === null)
            darkness = this.isThemeDark;
        else if (this.isThemeDark === darkness) 
            if (this.activeTheme === theme) return;
         else
            this.isThemeDark = darkness;

        this.activeTheme = theme;

        const cssClass = darkness === true ? theme + THEME_DARKNESS_SUFFIX : theme;

        const classList = this.overlayContainer.getContainerElement().classList;
        if (classList.contains(this.activeThemeCssClass))
            classList.replace(this.activeThemeCssClass, cssClass);
        else
            classList.add(cssClass);

        this.activeThemeCssClass = cssClass;
    

    constructor(overlayContainer: OverlayContainer) 
        this.setThemeClass('indigo-pink', false); // Default theme
    


Vea otras cosas en stackblitz.


ADVERTENCIA: Agregar 8 temas de material dinámico a la aplicación (4 luces + 4 oscuras) aumentó el tamaño de la construcción styles.css por ~420 kB en mi caso (comparado con uno static tema material).

Si para ti ha sido útil nuestro artículo, sería de mucha ayuda si lo compartieras con otros programadores así nos ayudas a dar difusión a nuestro contenido.

¡Haz clic para puntuar esta entrada!
(Votos: 2 Promedio: 5)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *