自己真实项目代码。这些类名是基于elementPlus的,如果是其他UI框架可自行修改类名即可
import { unref } from "vue";
import { changeToRgb } from "@/libs";
import { appStore } from "@/stores/app/app";
import { storeToRefs } from "pinia";
const mixColor = "#ffffff";
const el = document.documentElement;
export const setTheme = () => {
const app = appStore();
const { themeColor, fillColor, gradientColor, colorStyle } = storeToRefs(app);
const obj: any = {
primary: unref(themeColor), //默认按钮颜色要随主色题变化
info: unref(colorStyle).info,
warning: unref(colorStyle).warning,
danger: unref(colorStyle).danger,
success: "#67c23a",
error: "#f56c6c",
};
Object.keys(obj).forEach((key: string) => {
_color(key, obj[key]);
});
_bg({
gradientColor: gradientColor,
});
_border(colourBlend(themeColor.value, mixColor, 0.6));
_fill(gradientColor);
_text("#a39e9e");
};
const _color = (type: string, color: any) => {
const body: any = document.querySelector("body");
el.style.setProperty(`--el-color-${type}`, color);
body.style.setProperty(`--van-${type}-color`, color);
for (let i = 1; i < 10; i++) {
el.style.setProperty(
`--el-color-${type}-light-${i}`,
colourBlend(color, mixColor, i / 10)
);
// 按钮点击elementPlus用dark主题的2号颜色。(特殊处理)
el.style.setProperty(`--el-color-${type}-dark-2`, changeToRgb(color, 0.9));
}
};
const _bg = (params: any) => {
const { gradientColor } = params;
// 穿梭框背景,下拉框(不需要给透明度)
el.style.setProperty(
"--el-bg-color-overlay",
changeToRgb(gradientColor.value)
);
el.style.setProperty("--el-bg-color", changeToRgb(gradientColor.value));
el.style.setProperty(
"--el-disabled-bg-color",
changeToRgb(gradientColor.value, 0.7)
);
};
const _border = (color: any) => {
el.style.setProperty("--el-border-color", color);
const objSuffixs = ["light", "lighter", "extra-light"];
objSuffixs.forEach((key: string, index: number) => {
el.style.setProperty(
`--el-border-color-${key}`,
colourBlend(color, mixColor, (index + 1) / 10)
);
});
// xx项目特殊处理
el.style.setProperty(
"--el-border-color-lighter",
colourBlend("#2A598A", mixColor, 0)
);
};
const _fill = (color: any) => {
el.style.setProperty("--el-fill-color", unref(color));
el.style.setProperty("--el-fill-color-blank", changeToRgb(unref(color), 0.4));
const fillSuffixs = ["light", "lighter", "extra-light"];
fillSuffixs.forEach((key: string, index: number) => {
// el.style.setProperty(`--el-fill-color-${key}`, unref(color));
el.style.setProperty(
`--el-fill-color-${key}`,
changeToRgb(
colourBlend(unref(color), "#ffffff", (index + 1) / 10),
1 - ((index + 1) * 2) / 10
)
);
});
// xx项目特殊处理
el.style.setProperty(
"--el-fill-color-light",
colourBlend("#112C4D", "#ffffff", 0)
);
};
const _text = (color: any) => {
const app = appStore();
const { themeColor } = storeToRefs(app);
el.style.setProperty("--el-text-color-primary", "#ffffff");
el.style.setProperty("--el-text-color-regular", "#ffffff");
el.style.setProperty("--el-text-color-disabled", themeColor.value);
const textSuffixs = ["secondary", "placeholder"];
textSuffixs.forEach((key: string, index: number) => {
el.style.setProperty(
`--el-text-color-${key}`,
colourBlend(color, mixColor, (index + 1) / 10)
);
});
};
//混合
const colourBlend = (c1: any, c2: any, ratio: any) => {
ratio = Math.max(Math.min(Number(ratio), 1), 0);
const r1 = parseInt(c1.substring(1, 3), 16);
const g1 = parseInt(c1.substring(3, 5), 16);
const b1 = parseInt(c1.substring(5, 7), 16);
const r2 = parseInt(c2.substring(1, 3), 16);
const g2 = parseInt(c2.substring(3, 5), 16);
const b2 = parseInt(c2.substring(5, 7), 16);
let r: any = Math.round(r1 * (1 - ratio) + r2 * ratio);
let g: any = Math.round(g1 * (1 - ratio) + g2 * ratio);
let b: any = Math.round(b1 * (1 - ratio) + b2 * ratio);
r = ("0" + (r || 0).toString(16)).slice(-2);
g = ("0" + (g || 0).toString(16)).slice(-2);
b = ("0" + (b || 0).toString(16)).slice(-2);
return "#" + r + g + b;
};
如果有几套主题色,思路如下:
setTheme(‘主题色’),内部再写几套枚举值来对应各种所需颜色。
你也可以设置自己组件风格和elementPlus风格统一,代码如下:
@use "sass:map";
@use "./var.scss" as *;
@mixin fourCombine($prefix, $type) {
$fourName: $prefix + $type;
.#{$fourName} {
@content;
}
}
// 四色图 danger warning info primary
@each $linkType in $four {
@include fourCombine("sc_four_", $linkType) {
// color: map.get($four-colors, #{$linkType}, "base");
background: map.get($four-colors, #{$linkType}, "base");
}
}
// 所有颜色
@mixin colorCombine($prefix, $type) {
$fourName: $prefix + $type;
.#{$fourName} {
@content;
}
}
@each $linkType in $four {
@include colorCombine("sc_color_", $linkType) {
color: map.get($four-colors, #{$linkType}, "base");
}
}
// 为了实现card组件中字体颜色和外框颜色一致 实现数字type匹配字体颜色 (和字符串颜色保持一致)
@each $linkType in $four {
$i: index($four, $linkType);
@include colorCombine("sc_color_", $i) {
color: map.get($four-colors, #{$linkType}, "base");
}
}
// 尺寸
@mixin sizeCombine($prefix, $type) {
$fourName: $prefix + $type;
.#{$fourName} {
@content;
}
}
@each $linkType in $size {
@include colorCombine("sc-text--", $linkType) {
font-size: map.get($sc_size, #{$linkType}, "size");
}
}
//var.scss
$four: danger, warning, info, primary, purple, green, cyan, blue, normal, white; /*四色图( 重大危险 较大危险 一般分险 低分险) 后面颜色可扩展*/
$four-colors: (
"danger": (
"base": #ff3400,
"type": 1,
),
"warning": (
"base": #ffab3f,
"type": 2,
),
"info": (
"base": #f3ee55,
"type": 3,
),
"primary": (
"base": #2ffff3,
"type": 4,
),
"purple": (
"base": #9097ff,
"type": 5,
),
"green": (
"base": #19ff70,
"type": 6,
),
"cyan": (
"base": #00fcf7,
"type": 7,
),
"blue":
(
"base": #539cff,
"type": 8,
),
"normal": (
"base": #0ceda8,
"type": 9,
),
"white": (
"base": #fff,
"type": 10,
)
);
$size: large medium base small;
$sc_size: (
"large": (
"size": var(--sc-font-size-large),
),
"medium": (
"size": var(--sc-font-size-medium),
),
"base": (
"size": var(--sc-font-size-base),
),
"small": (
"size": var(--sc-font-size-small),
),
);
这里只是整体思路,可通过这种循环的方式生成一套类似与elementPlus的样式。写组件的时候只要使用这些类名即可。当然你也可以手动将elementPlus全局的变量值修改
--el-text-color-primary: #00fcf7;
--el-bg-color: #fff;
扩展:通过循环生成常用的css
// mt100,mr24,pl10,w100,h323
@for $i from 0 through 200 {
.mt#{$i} {
margin-top: 1px * $i;
}
.mb#{$i} {
margin-bottom: 1px * $i;
}
.ml#{$i} {
margin-left: 1px * $i;
}
.mr#{$i} {
margin-right: 1px * $i;
}
}
@for $i from 0 through 200 {
.pt#{$i} {
padding-top: 1px * $i;
}
.pb#{$i} {
padding-bottom: 1px * $i;
}
.pl#{$i} {
padding-left: 1px * $i;
}
.pr#{$i} {
padding-right: 1px * $i;
}
}
@for $i from 0 through 3000 {
.w#{$i} {
width: 1px * $i;
}
.h#{$i} {
height: 1px * $i;
}
}