【问题标题】:How to use $mdTheming to apply theme to custom element如何使用 $mdTheming 将主题应用于自定义元素
【发布时间】:2016-03-10 01:26:08
【问题描述】:

我一直在想办法使用$mdTheming 库提供的$mdTheming 服务来应用通过$mdThemingProvider 配置的主题。

简单来说:

考虑一个元素

<div class="md-primary" theme></div>

在这种情况下,theme 指令必须注入主色配置到主题。

以下是我尝试使用的方法,经过angular-material的代码

只是看看他们是怎么做到的

export function ThemeDirective($mdTheming) {
 'ngInject';
 
 let directive = {
   restrict: 'A',
   link: (scope, element) => {
    $mdTheming(element);
   }
 };

  return directive
}

上面的代码似乎没有做任何事情。我确定我忽略了一些东西。需要帮助。

【问题讨论】:

    标签: angularjs angular-material


    【解决方案1】:

    这可能对您的研究有所帮助...您可以将其用于将主题应用于您的指令。我从链接开始https://material.angularjs.org/latest/Theming/05_under_the_hood

    当您进一步查看 Angular 代码时,您会发现常量 $MD_THEME_CSS。这基本上是一个 css 文件,其中包含每个指令的所有样式 - 但它使用它们插入的标签进行格式化:

    
        ...
        md-input-container.md-THEME_NAME-theme .md-input {
            color: {{foreground-1}};
            border-color: {{foreground-4}};
            text-shadow: {{foreground-shadow}};
        }
    
        md-input-container.md-THEME_NAME-theme .md-input::-webkit-input-placeholder,md-input-container.md-THEME_NAME-theme .md-input::-moz-placeholder,md-input-container.md-THEME_NAME-theme .md-input:-moz-placeholder,md-input-container.md-THEME_NAME-theme .md-input:-ms-input-placeholder {
            color: {{foreground-3}};
        }
        ...
    

    他们用颜色值替换的这些标签显示在 mdThemingProvider 的文档中......

    
        /* Some Example Valid Theming Expressions
         * =======================================
         * Intention group expansion: (valid for primary, accent, warn, background)
         * {{primary-100}} - grab shade 100 from the primary palette
         * {{primary-100-0.7}} - grab shade 100, apply opacity of 0.7
         * {{primary-100-contrast}} - grab shade 100's contrast color
         * {{primary-hue-1}} - grab the shade assigned to hue-1 from the primary palette
         * {{primary-hue-1-0.7}} - apply 0.7 opacity to primary-hue-1
         * {{primary-color}} - Generates .md-hue-1, .md-hue-2, .md-hue-3 with configured shades set for each hue
         * {{primary-color-0.7}} - Apply 0.7 opacity to each of the above rules
         * {{primary-contrast}} - Generates .md-hue-1, .md-hue-2, .md-hue-3 with configured contrast (ie. text) color shades set for each hue
         * {{primary-contrast-0.7}} - Apply 0.7 opacity to each of the above rules
         *
         * Foreground expansion: Applies rgba to black/white foreground text
         * {{foreground-1}} - used for primary text
         * {{foreground-2}} - used for secondary text/divider
         * {{foreground-3}} - used for disabled text
         * {{foreground-4}} - used for dividers
         */
    

    在定义完所有主题后,该字符串会在运行时由 generateAllThemes() 格式化。这会将这些样式注入到

    元素中 - 正如您在 chrome 中检查页面所见: enter image description here

    现在我以前从未亲自这样做过,所以我不知道这里的标准,也找不到它的文档。但是我假设您可以以某种方式调用 GenerateTheme() 来生成您自己的样式以在您的 html 中使用......或者只是借用一些已经为核心代码生成的类。

    但是,我使用自己的服务而不是他们的服务做了类似的事情。

    这是我过去使用过的解决方案的一个可能开始...在我在 .config() 中定义主题后,我编写了一个简单的提供程序来保存我的主题调色板。然后我编写了一个服务来将主题颜色代码连接到实际的 rgb 颜色。希望它不会太 hacky。

    (function() {
      var app = angular.module('MyApp', ['ngMaterial', 'ngMessages'])
    
      // The provider... I store the color palette here since a service isn't available during .config();
      .provider('colorPalette', function colorPaletteProvider() {
        var _PALETTE = {};
    
        this.SetPalette = function(value) {
          _PALETTE = value
        }
    
        this.$get = [
          function() {
            return _PALETTE;
          }
        ];
      })
    
      .config(function($mdThemingProvider, colorPaletteProvider) {
        var xoMap = $mdThemingProvider.extendPalette('purple', {
          '500': '833A96'
        });
        $mdThemingProvider.definePalette('XO-Main', xoMap);
    
        // add a couple of themes
        $mdThemingProvider.theme('default')
          .primaryPalette('XO-Main')
          .accentPalette('pink', {
            "default": "500",
            "hue-1": "50"
          })
          .backgroundPalette('grey');
    
        $mdThemingProvider.theme('order')
          .primaryPalette('XO-Main')
          .accentPalette('light-blue', {
            "default": "500",
            "hue-1": "50"
          });
    
        // save the palette so i can see it later
        colorPaletteProvider.SetPalette($mdThemingProvider._PALETTES);
      })
    
      .run(function($interpolate, themeColorsService) {
        // inject some styles into the head
        var orderTheme = themeColorsService.GetColors("order");
        var myStyle = $interpolate(".nav-icon-order {color: {{accent.default.bg}};}")(orderTheme);
        console.debug(myStyle);
        themeColorsService.AddStyle(myStyle);
        themeColorsService.AddStyle($interpolate("md-toolbar.hpbx-toolbar-accent-order, .panel-heading.hpbx-toolbar-accent-order { border-bottom: 5px solid {{accent.default.bg}};}")(orderTheme));
    
      });
    
      // The controller
      app.controller("AppCtrl", function($scope, themeColorsService) {
        $scope.themeColors = themeColorsService.GetColors("default");
      });
    })();
    
    // example directive where the theme is passed in
    angular.module('MyApp').directive('theme', function (themeColorsService) {
            return {
                restrict: "A",
                transclude: true,
                template: "<div ng-style='{color: themeColors.primary.default.bg}' ng-transclude></div>",
                scope: {
                    themeName: "="
                },
                controller: function ($scope, $element, $attrs) {
                    $scope.themeColors = themeColorsService.GetColors("default");
                }
            }
        });
    
    // The service
    angular.module('MyApp').service("themeColorsService", function(colorPalette, $mdTheming) {
      this.themes = {};
    
      // tie the color codes together with the palettes
      this.GetColors = function(theme) {
        var returnVal = {};
        if (!this.themes.hasOwnProperty(theme)) {
          theme = $mdTheming.THEMES[theme];
    
          _.keys(theme.colors).forEach(function(key) {
            returnVal[key] = {};
            var palette = theme.colors[key].name;
            if (!_.isUndefined(palette)) {
              _.keys(theme.colors[key].hues).forEach(function(hue) {
                var c = theme.colors[key].hues[hue];
                var p = colorPalette[palette][c];
    
                returnVal[key][hue] = {};
                returnVal[key][hue].bg = getRGB(p.value);
                returnVal[key][hue].fg = getRGB(p.contrast);
              });
            }
          });
    
          this.themes[theme] = _.cloneDeep(returnVal);
        }
    
        return this.themes[theme];
      };
    
      var getRGB = function(value) {
        var returnVal = "";
    
        if (value.length == 4) {
          returnVal = "rgba(" + value[0] + "," + value[1] + "," + value[2] + "," + value[3] + ")";
        } else if (value.length == 3) {
          returnVal = "rgb(" + value[0] + "," + value[1] + "," + value[2] + ")";
        }
    
        return returnVal;
      };
    
      // insert a style into the head element
      this.AddStyle = function(styleContent) {
        var head = document.head;
        var firstChild = head ? head.firstElementChild : null;
    
        var style = document.createElement('style');
        style.setAttribute('xo-theme-style', '');
        style.appendChild(document.createTextNode(styleContent));
        head.insertBefore(style, firstChild);
      };
    });
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-animate.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.min.js"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-animate.min.js"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-messages.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-route.min.js"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-aria.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-material/1.0.6/angular-material.js"></script>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/angular-material/1.0.6/angular-material.css" rel="stylesheet" />
    
    <html ng-app="MyApp">
    
    <body>
      <div ng-controller="AppCtrl">
        <div>I'm unstyled</div>
        
        <!-- style using ng-style -->
        <div ng-style="{color: themeColors.primary.default.bg}">I'm styled with ngStyle</div>
        
        <!-- use your injected css style -->
        <div class="nav-icon-order">I'm using an injected css class</div>
        
        <!-- send it to a directive the way you listed in your example -->
        <div theme>This is a styled directive</div>
        
        <!-- show the themeColors object -->
        <pre>themeColors:{{themeColors | json}}</pre>
      </div>
    </body>
    
    </html>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-30
      • 1970-01-01
      • 1970-01-01
      • 2010-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-14
      相关资源
      最近更新 更多