前言
关于ElementPlus的基础主题色自定义可以参阅《【VUE】ElementPlus之自定义主题样式和命名空间》
有了上面基础的了解,我们知道ElementPlus的主题色调是基于CSS3变量特性进行全局控制的, 那么接下来我们也基于CSS3变量来实现主题色调的动态切换效果;
主要控制的色调类型有:primary、success、warning、danger、error、info 针对这六个色调类型分别进行0、3、5、7、8、9级的渐变色定制
以下是默认情况下的主题颜色定义:
接下来,我们基于以下环境来实操下:
vue: ^3.3.4vite: ^4.4.11sass: ^1.58.3element-plus: ^2.3.4pinia: ^2.1.7
实现
默认主题色下的按钮组件色调:
预想效果:
在实现具体交互之前,我们先准备几个辅助小工具
颜色状态管理器
既然是动态切换,那么我们就需要一个容器来记录当下的一些色调信息,便于整体性的调整 以下仅抛个砖,具体业务调整根据自己需要来哈~
import { defineStore } from "pinia";
import ColorUnit from "@/unit/ColorUnit";
export const useColorStore = defineStore("color", () => {
function setThemeColor(colorMap) {
let _namespace = "el";
colorMap.forEach((colorItem) => {
setPropertyColor(`--${_namespace}-color-${colorItem[0]}`, colorItem[1]);
themeColorGradient(`--${_namespace}-color-${colorItem[0]}-light-#level#`,"lighten",colorItem[1]);
setPropertyColor(`--${_namespace}-color-${colorItem[0]}-dark-2`,colorItem[1],"darken");
// themeColorGradient(`--${_namespace}-color-${colorItem[0]}-dark-#level#`,"darken",colorItem[1]);
});
}
/**
* 将css3变量设置到document中方便全局调用
*/
function setPropertyColor(varName, color, funName, level) {
level = level ? level : 0;
funName = funName ? funName : "lighten";
document.documentElement.style.setProperty(
varName,
ColorUnit[funName](color, level / 10)
);
}
/**
* 生成主色的其余渐变色并修改对应CSS3变量值
*/
function themeColorGradient(varName, funName, themeColor, themeLevel) {
themeColor = themeColor ? themeColor : '#409eff';
themeLevel = themeLevel ? themeLevel : [3, 5, 7, 8, 9];
themeLevel.forEach(function (level) {
setPropertyColor(
varName.replace("#level#", level),
themeColor,
funName,
level
);
});
}
return {
setThemeColor,
};
});
颜色编码生成工具
根据前言描述,我们得知,需要根据一个十六进制的色值,生成其余的渐变色值出来,手动配置的话就太麻烦了 所以我们先来封装一个ColorUnit工具来辅助我们进行色调的配置
// file: src/unit/ColorUnit.js
// 代码载取来至:https://gitee.com/lolicode/scui/blob/master/src/utils/color.js
export default {
//hex颜色转rgb颜色
HexToRgb(str) {
str = str.replace("#", "")
var hxs = str.match(/../g)
for (var i = 0; i < 3; i++) hxs[i] = parseInt(hxs[i], 16)
return hxs
},
//rgb颜色转hex颜色
RgbToHex(a, b, c) {
var hexs = [a.toString(16), b.toString(16), c.toString(16)]
for (var i = 0; i < 3; i++) {
if (hexs[i].length == 1) hexs[i] = "0" + hexs[i]
}
return "#" + hexs.join("");
},
//加深
darken(color, level) {
var rgbc = this.HexToRgb(color)
for (var i = 0; i < 3; i++) rgbc[i] = Math.floor(rgbc[i] * (1 - level))
return this.RgbToHex(rgbc[0], rgbc[1], rgbc[2])
},
//变淡
lighten(color, level) {
var rgbc = this.HexToRgb(color)
for (var i = 0; i < 3; i++) rgbc[i] = Math.floor((255 - rgbc[i]) * level + rgbc[i])
return this.RgbToHex(rgbc[0], rgbc[1], rgbc[2])
}
}
整合
有了上面俩个帮手,现在整合起来的具体应用
template部分
@click="setThemeColor(item.color, item.label)"
:style="{'--color':item.color[0][1]}">
{{ item.label }}
{{ item.color[0][0] }}
{{ item.color[0][1] }}
当前主题:{{ themeName }}
script部分
import {ref} from "vue"
import { useColorStore } from "@/stores/color";
// ...
const themeName = ref('默认主题');
const colorStore = useColorStore();
// ...
let _theme = [
{label:'默认主题', color:[["primary", "#409EFF"], ["success", "#67C23A"], ["warning", "#E6A23C"], ["danger", "#F56C6C"], ["error", "#F56C6C"], ["info", "#909399"]]},
{label:'自定义主题1', color:[["primary", "#1984f3"], ["success", "#55DE12"], ["warning", "#EA9412"], ["danger", "#E12020"], ["error", "#E12020"], ["info", "#209399"]]},
{label:'自定义主题2', color:[["primary", "#0A4680"], ["success", "#276409"], ["warning", "#815410"], ["danger", "#931d1d"], ["error", "#931D1D"], ["info", "#454A55"]]},
];
// ...
function setThemeColor(colorMap, label) {
themeName.value = label;
colorStore.setThemeColor(colorMap);
}
// ...
相关链接
发表评论