vue3+element-plus实现动态换肤

这里实现的国际化使用到了两个包

npm i rgb-hex
npm i css-color-function

 css-color-function是用于解析和转换 CSS 颜色函数表达式。

输入示例:"color(#409EFF tint(30%))"

输出示例:"rgb(121, 187, 255)"

这个函数能够处理各种复杂的颜色表达式,比如:

  • color(primary shade(10%)) - 将颜色加深 10%
  • color(primary tint(30%)) - 将颜色变亮 30%
  • color(primary alpha(50%)) - 将颜色透明度设为 50%

rgbHex()是 rgb-hex 库提供的方法,用于将 RGB 颜色值转换为十六进制格式

这两个工具包就实现颜色转换

1.实现动态换肤第-修改element-plus的颜色

实现步骤

1. 根据主色生成色值表

 {
  "shade-1": "color(primary shade(10%))",
  "light-1": "color(primary tint(10%))",
  "light-2": "color(primary tint(20%))",
  "light-3": "color(primary tint(30%))",
  "light-4": "color(primary tint(40%))",
  "light-5": "color(primary tint(50%))",
  "light-6": "color(primary tint(60%))",
  "light-7": "color(primary tint(70%))",
  "light-8": "color(primary tint(80%))",
  "light-9": "color(primary tint(90%))",
  "subMenuHover": "color(primary tint(70%))",
  "subMenuBg": "color(primary tint(80%))",
  "menuHover": "color(primary tint(90%))",
  "menuBg": "color(primary)"
}

//生成色值表
const generateColors = (primary: string) => {
  if (!primary) return {};
  const colors: Record<string, string> = {
    primary
  }
  Object.keys(formula as FormulaType).forEach(key => {
    const value = (formula as FormulaType)[key].replace(/primary/g, primary);
    colors[key] = '#' + rgbHex(color.convert(value));
  })
  return colors;
}

获取当前 element-plus 的默认样式表,并且把需要更改的色值打上标记 

    import axios from 'axios';
    import { version } from 'element-plus/package.json';
    //获取原始样式
    const getOriginalStyle = async () => {
      const url = `https://unpkg.com/element-plus@${version}/dist/index.css`;
      const { data } = await axios.get(url);
      return getThemeStyle(data);
    }
    //获取主题样式
    const getThemeStyle = (data: string) => {
      const colorMap: Record<string, string> = {
        '#3a8ee6': 'shade-1',
        '#409eff': 'primary',
        '#53a8ff': 'light-1', 
        '#66b1ff': 'light-2',
        '#79bbff': 'light-3',
        '#8cc5ff': 'light-4',
        '#a0cfff': 'light-5',
        '#b3d8ff': 'light-6',
        '#c6e2ff': 'light-7',
        '#d9ecff': 'light-8',
        '#ecf5ff': 'light-9'
      };
      
      // 添加 RGB 格式颜色映射
      const rgbColorMap: Record<string, string> = {
        'rgb\\(121\\.3,\\s*187\\.1,\\s*255\\)': 'light-3',
        'rgb\\(159\\.5,\\s*206\\.5,\\s*255\\)': 'light-5',
        'rgb\\(197\\.7,\\s*225\\.9,\\s*255\\)': 'light-7',
        'rgb\\(216\\.8,\\s*235\\.6,\\s*255\\)': 'light-8',
        'rgb\\(235\\.9,\\s*245\\.3,\\s*255\\)': 'light-9'
      };
    
      // 替换十六进制颜色
      Object.keys(colorMap).forEach(key => {
        const value = colorMap[key];
        data = data.replace(new RegExp(key, 'ig'), value);
      });
      
      // 替换 RGB 格式颜色(使用已转义的正则模式)
      Object.keys(rgbColorMap).forEach(pattern => {
        const value = rgbColorMap[pattern];
        data = data.replace(new RegExp(pattern, 'ig'), value);
      });
      
      return data;
    }
    

    2.找到我们想要替换的样式部分,通过正则完成替换

    export const generateNewStyle = async (primaryColor: string) => {
      // 1. 根据主色生成色值表
      const colors = generateColors(primaryColor);
      // 2. 获取当前 element-plus 的默认样式表,并且把需要更改的色值打上标记
      let cssText = await getOriginalStyle();
      // 3. 遍历生成的色值表,在 默认样式表 进行全局替换
      if (colors) {
        Object.keys(colors).forEach(key => {
          cssText = cssText.replace(new RegExp('(:|\\s+)' + key, 'g'), '$1' + colors[key]);
        });
      }
      return cssText;
    };

    3.把替换后的样式写入到style标签中,利用样式优先替换固有的样式

    
    export const writeNewStyle = (newStyle: string) => {
      const style = document.createElement('style');
      style.innerText = newStyle;
      document.head.appendChild(style);
    };
    

    2.将修改的的颜色应用到自己的样式

    这里就不做演示,就是把修改的颜色通过vuex和localstorage存储起来这样就,把它应用到自己的样式,这样就实现了动态换肤

    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值