主题色切换
什么是主题色切换,所谓的主题色切换就是我们通过自定义的方式去修改elementUI原有的主题色,以达到我们业务所要使用的多(单)色彩切换.
静态切换
elementui 采用的是scss进行实现的样式 我们的项目也使用的是scss 因此我们在项目中创建一个element-variables.scss文件存放我们修改的主题色
/* 改变主题色变量 */
$--color-primary: 自定义的主题色;
/* 改变 icon 字体路径变量,必需 */
$--font-path: '~element-ui/lib/theme-chalk/fonts';
@import "~element-ui/packages/theme-chalk/src/index";
在项目的入口文件中引用定义的文件
import Vue from 'vue'
import Element from 'element-ui'
import './element-variables.scss'
Vue.use(Element)
如果项目中没有使用scss的话则参考elementui官网进行配置
element-ui
动态切换
动态切换则是我们通过element-ui的颜色选择器,和获取远端element-ui主题样式,通过标签匹配替换的方式进行改变的。
封装的组件
<template>
<el-color-picker v-model="theme" />
</template>
<script>
const version = require("element-ui/package.json").version;
const ORIGINAL_THEME = "#409EFF";
export default {
name:"theme",
props: {
//接收初始化传递过来的颜色
color: String,
},
data() {
return {
//远端请求回来的css数据
chalk: "",
//绑定的主题色
theme: "",
};
},
computed: {
//默认主题色
defaultTheme() {
return this.color;
},
},
watch: {
defaultTheme: {
handler: function (val, oldVal) {
//将默认主题色赋值给颜色选择器
this.theme = val;
},
immediate: true,
},
//监听绑定的颜色的变化
async theme(val) {
const oldVal = this.chalk ? this.theme : ORIGINAL_THEME;
if (typeof val !== "string") return;
//新的主题色相关
const themeCluster = this.getThemeCluster(val.replace("#", ""));
//旧的主题相关色
const originalCluster = this.getThemeCluster(oldVal.replace("#", ""));
//如果主题的样式文件不存在则从远端重新获取,否则直接加载新的样式
await this.getCSSString();
this.getHandler(themeCluster);
const styles = [].slice
.call(document.querySelectorAll("style"))
.filter((style) => {
const text = style.innerText;
return (
new RegExp(oldVal, "i").test(text) && !/Chalk Variables/.test(text)
);
});
console.log(styles,'wewe222')
styles.forEach((style) => {
const { innerText } = style;
if (typeof innerText !== "string") return;
style.innerText = this.updateStyle(
innerText,
originalCluster,
themeCluster
);
});
this.$emit("color-update", val);
},
},
methods: {
// 修改element-ui主题样式表颜色
updateStyle(style, oldCluster, newCluster) {
let newStyle = style;
oldCluster.forEach((color, index) => {
newStyle = newStyle.replace(new RegExp(color, "ig"), newCluster[index]);
});
return newStyle;
},
// 生成新的样式表
getHandler(themeCluster) {
//获取源style
const originalCluster = this.getThemeCluster(
ORIGINAL_THEME.replace("#", "")
);
const newStyle = this.updateStyle(
this.chalk,
originalCluster,
themeCluster
);
let styleTag = document.getElementById("chalk-style");
if (!styleTag) {
styleTag = document.createElement("style");
styleTag.setAttribute("id", "chalk-style");
document.head.appendChild(styleTag);
}
styleTag.innerText = newStyle;
},
// 获取element-ui主题样式
getCSSString() {
const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css`;
return new Promise((resolve) => {
const xhr = new XMLHttpRequest();
xhr.onreadystatechange = () => {
if (xhr.readyState === 4 && xhr.status === 200) {
//获取到的element的样式
this.chalk = xhr.responseText.replace(/@font-face{[^}]+}/, "");
resolve();
}
};
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) {
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));
console.log(clusters,'wewe')
return clusters;
},
},
};
</script>
全网站色彩切换
思路:全网站的色彩切换 其根本的原理在于 在body上去添加不同的class 同时通过class名匹配的方式去修改 其他内容的颜色
//页面初次加载的时候我们默认一个class
localStorage.setItem('theme',"default")
主题切换
handleChangeTheme(theme){
//主题切换
let theme=theme?theme:"default"
localStorage.setItem('theme',theme)
dcoumnet.getElementByTagName('body')[0].className='theme'
/*在加载的scss文件中去定义每个主题下对相应的颜色变化*/
.logo{
color:"pink" /*默认主题下是粉色*/
}
.dask{
.logo{
color:"white"/*黑色主题下是白色*/
}
}
这样就实现了全网站的色彩切换,有个不好的地方就是这种可能就需要我们写两组或者多组的样式 实现样式,主题色的切换。
接下来探索更优的主题色彩切换方案