如何使用 $mdTheming 将主题应用到自定义元素
How to use $mdTheming to apply theme to custom element
我一直在想办法使用 angular-material
库提供的 $mdTheming
服务来应用通过 $mdThemingProvider
配置的主题。
简单来说:
考虑一个元素
<div class="md-primary" theme></div>
theme
指令在这种情况下必须注入主要颜色配置为主题。
下面是我在阅读 angular-material
的代码后尝试使用的方法
Just to see how they might have done it
export function ThemeDirective($mdTheming) {
'ngInject';
let directive = {
restrict: 'A',
link: (scope, element) => {
$mdTheming(element);
}
};
return directive
}
上面的代码似乎没有做任何事情。我确定我忽略了一些东西。需要帮助。
这可能有助于您的研究...您可以使用它来将主题应用到您的指令中。我从 link 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>
我一直在想办法使用 angular-material
库提供的 $mdTheming
服务来应用通过 $mdThemingProvider
配置的主题。
简单来说:
考虑一个元素
<div class="md-primary" theme></div>
theme
指令在这种情况下必须注入主要颜色配置为主题。
下面是我在阅读 angular-material
的代码后尝试使用的方法
Just to see how they might have done it
export function ThemeDirective($mdTheming) {
'ngInject';
let directive = {
restrict: 'A',
link: (scope, element) => {
$mdTheming(element);
}
};
return directive
}
上面的代码似乎没有做任何事情。我确定我忽略了一些东西。需要帮助。
这可能有助于您的研究...您可以使用它来将主题应用到您的指令中。我从 link 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>