element-plus 动态自定义主题颜色
颜色的HEX格式
颜色的HEX
格式是#
+六位数字/字母
,其中六位数字/字母
是一种十六进制的表达方式。这六位分别两个一组,从左到右分别表示红
、绿
、蓝
。00
表示最小,十进制是0
;FF
表示最大,十进制是255
。通俗点讲,某个颜色的数值越大,包含这个颜色就越多。如:#000000
-黑色、#FFFFFF
-白色、#FF0000
-红色、#00FF00
-绿色、#0000FF
-蓝色。
HEX格式颜色变亮、变暗
通过上文的介绍,我们可以知道Element
的hover
颜色变亮了,即颜色的数值变大了,那我们只要对要修改的颜色数值变大即可。那就需要用到以下的方法:
HEX格式转RGB格式
hex2Rgb(color) {
color = color.replace('#', '')
const result = color.match(/../g)
for (let i = 0; i < 3; i++) {
result[i] = parseInt(result[i], 16)
}
return result
}
RGB格式转HEX格式
rgb2Hex(r, g, b) {
const hexs = [r.toString(16), g.toString(16), b.toString(16)]
for (let i = 0; i < 3; i++) {
if (hexs[i].length === 1) {
hexs[i] = '0' + hexs[i]
}
}
const result = '#' + hexs.join('')
return result
}
使颜色变亮
lighten(color, level) {
const rgb = hex2Rgb(color)
for (let i = 0; i < 3; i++) {
rgb[i] = Math.floor((255 - rgb[i]) * level + rgb[i])
}
const result = rgb2Hex(rgb[0], rgb[1], rgb[2])
return result
}
使颜色变暗
darken(color, level) {
const rgb = hex2Rgb(color)
for (let i = 0; i < 3; i++) {
rgb[i] = Math.floor(rgb[i] * (1 - level))
}
const result = rgb2Hex(rgb[0], rgb[1], rgb[2])
return result
}
解决问题
在修改主色的时候将对应的其他CSS变量
进行变亮或者变暗即可。一般这种主题都是会存储浏览器Storage
中,可以结合实际情况配合vuex
或者pinia
使用。
// utils.js
export function hex2Rgb(color) {
color = color.replace('#', '')
const result = color.match(/../g)
for (let i = 0; i < 3; i++) {
result[i] = parseInt(result[i], 16)
}
return result
}
export function rgb2Hex(r, g, b) {
const hexs = [r.toString(16), g.toString(16), b.toString(16)]
for (let i = 0; i < 3; i++) {
if (hexs[i].length === 1) {
hexs[i] = '0' + hexs[i]
}
}
const result = '#' + hexs.join('')
return result
}
export function lighten(color, level) {
const rgb = hex2Rgb(color)
for (let i = 0; i < 3; i++) {
rgb[i] = Math.floor((255 - rgb[i]) * level + rgb[i])
}
const result = rgb2Hex(rgb[0], rgb[1], rgb[2])
return result
}
export function darken(color, level) {
const rgb = hex2Rgb(color)
for (let i = 0; i < 3; i++) {
rgb[i] = Math.floor(rgb[i] * (1 - level))
}
const result = rgb2Hex(rgb[0], rgb[1], rgb[2])
return result
}
// index.vue
<template>
<div class="container">
<el-button>Default</el-button>
<el-button v-for="item in types" :key="item" :type="item">{{ item }}</el-button>
<hr>
<el-radio-group v-model="radio" @change="radioChangeHandle">
<el-radio v-for="item in types" :key="item" :label="item" size="large">{{ item }}</el-radio>
</el-radio-group>
<br>
<el-color-picker v-model="color" @change="colorChangeHandle" color-format="hex" :show-alpha="false" />
</div>
</template>
<script setup>
import { ref } from 'vue'
import { lighten, darken } from '@/utils'
const el = document.documentElement
const types = ref(['primary', 'success', 'info', 'warning', 'danger'])
const radio = ref('primary')
const color = ref(getComputedStyle(el).getPropertyValue(`--el-color-${radio.value}`))
const radioChangeHandle = () => {
const value = getComputedStyle(el).getPropertyValue(`--el-color-${radio.value}`)
color.value = value
}
const colorChangeHandle = (value) => {
el.style.setProperty(`--el-color-${radio.value}`, value)
for (let i = 1; i <= 9; i++) {
el.style.setProperty(`--el-color-${radio.value}-light-${ i }`, lighten(value, i / 10))
el.style.setProperty(`--el-color-${radio.value}-dark-${ i }`, darken(value, i / 10))
}
}
</script>
<style>
.container {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -100%);
width: 50%;
text-align: center;
}
</style>