一、效果展示
二、实现思路
读取.css文件和style样式,然后进行全局替换
1、核心代码
import {
mapGetters
} from "vuex";
const version = require("element-ui/package.json").version; // element-ui version from node_modules
import theme from "@/config/theme";
let ORIGINAL_THEME = []; // default color
export default function () {
return {
data() {
return {
themeVal: 'theme-primary'
}
},
created() {
ORIGINAL_THEME = this.deepClone(theme["theme-primary"]);
this.themeVal = this.colorName;
},
watch: {
themeVal(val, oldVal) {
this.$store.commit("SET_COLOR_NAME", val);
this.box = false;
//this.updateTheme(val, oldVal);
this.updateTheme(theme[val], theme[oldVal]);
}
},
computed: {
...mapGetters(["colorName"])
},
methods: {
getNewArr(val) {
const themeClusterArr = [];
//前面5组数据单独处理
for (let i = 0; i < 5; i++) {
let themeCluster = this.getThemeCluster(val[i].replace("#", "")); //主题色同组
themeClusterArr.push(themeCluster);
}
//删掉前五个
val.splice(0, 5);
let newArr = themeClusterArr.flat();
val.unshift(...newArr);
},
updateTheme(val, oldVal) {
const head = document.getElementsByTagName("head")[0];
this.getNewArr(val);
this.getNewArr(oldVal);
const getHandler = (variable, id) => {
return () => {
this.getNewArr(ORIGINAL_THEME);
const newStyle = this.updateStyle(
this[variable],
ORIGINAL_THEME,
val
);
let styleTag = document.getElementById(id);
if (!styleTag) {
styleTag = document.createElement("style");
styleTag.setAttribute("id", id);
head.appendChild(styleTag);
}
styleTag.innerText = newStyle;
};
};
const chalkHandler = getHandler("chalk", "chalk-style");
if (!this.chalk) {
const url = `/cdn/element-ui/${version}/theme-chalk/index.css`;
this.getCSSString(url, chalkHandler, "chalk");
} else {
chalkHandler();
}
const link = [].slice.call(
document.getElementsByTagName("head")[0].getElementsByTagName("link")
);
for (let i = 0; i < link.length; i++) {
const style = link[i];
if (style.href.includes('css') && !style.href.includes("xctheme")) {
this.getCSSString(style.href, innerText => {
const newStyle = this.updateStyle(
innerText,
ORIGINAL_THEME,
val
);
let styleTag = document.getElementById(i);
if (!styleTag) {
styleTag = document.createElement("style");
styleTag.id = i;
styleTag.innerText = newStyle;
head.appendChild(styleTag);
}
});
}
}
const styles = [].slice.call(document.querySelectorAll("style"))
styles.forEach(style => {
const {
innerText
} = style;
if (typeof innerText !== "string") return;
style.innerText = this.updateStyle(
innerText,
oldVal,
val
);
});
},
updateStyle(style, oldCluster, newCluster) {
let newStyle = style;
oldCluster.forEach((color, index) => {
newStyle = newStyle.replace(new RegExp(color, "ig"), newCluster[index]);
});
return newStyle;
},
getCSSString(url, callback, variable) {
const xhr = new XMLHttpRequest();
xhr.onreadystatechange = () => {
if (xhr.readyState === 4 && xhr.status === 200) {
if (variable) {
this[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, "");
}
callback(xhr.responseText);
}
};
xhr.open("GET", url);
xhr.send();
},
getThemeCluster(theme) {
const tintColor = (color, tint) => {
let red = parseInt(color.slice(0, 2), 16);
let green = parseInt(color.slice(2, 4), 16);
let blue = parseInt(color.slice(4, 6), 16);
if (tint === 0) {
// when primary color is in its rgb space
return [red, green, blue].join(",");
} else {
red += Math.round(tint * (255 - red));
green += Math.round(tint * (255 - green));
blue += Math.round(tint * (255 - blue));
red = red.toString(16);
green = green.toString(16);
blue = blue.toString(16);
return `#${red}${green}${blue}`;
}
};
const shadeColor = (color, shade) => {
let red = parseInt(color.slice(0, 2), 16);
let green = parseInt(color.slice(2, 4), 16);
let blue = parseInt(color.slice(4, 6), 16);
red = Math.round((1 - shade) * red);
green = Math.round((1 - shade) * green);
blue = Math.round((1 - shade) * blue);
red = red.toString(16);
green = green.toString(16);
blue = blue.toString(16);
return `#${red}${green}${blue}`;
};
const clusters = [theme];
for (let i = 0; i <= 9; i++) {
clusters.push(tintColor(theme, Number((i / 10).toFixed(2))));
}
clusters.push(shadeColor(theme, 0.1));
return clusters;
}
}
}
}
2、一一对应的替换文件
//前面五种主题色,前面五种可生成渐变色 【primary,success,warning,danger,info】
let theme = {
'theme-primary': ["#409EFF","#67C23A","#E6A23C","#F56C6C","#909399","#fafafa","#f0f2f5","#EBEEF5","#606266","#FFFFFF","#DCDFE6","#f6f6f6"],
'theme-red': ["#2589A4","#3A41C2","#7AE63C","#611013","#2E2F30","#f0f2f5","#060606","#2D3A44","#AAB1C2","#000000","#546B85","#2D3A44"],
}
export default theme;