记录一次主题色自动适应方案

背景

随着前端越来越多的页面嵌入到不同平台,或者同一个页面嵌入到不同的平台,但平台的主题色是不相同的,因此需要实现页面主题色自动适应父级框架

实现方案

1.qiankun框架

开发环境:由于没有做到严格的样式隔离,父项目定义的变量和样式会被子项目获取到,所以阴差阳错的导致子页面会和父框架主题色相同

生产环境:会执行严格的样式隔离,所以默认子页面不会继承到父框架的主题配置

2.iframe框架

需要嵌入的子页面,sso配置时通过传参themeColor,即可实现子页面主题的切换,如:http://127.0.0.1:8886/cop/page/#/index?themeColor=ff0000

因此我们主要关注子页面内的颜色处理

1.themeUtils.js

根据element-plus的颜色变量,自己实现一套颜色逐级淡化和颜色逐级加深的颜色算法工具,覆盖element-plus的颜色变量

首要要知道element-plus有哪些主题颜色变量

类型上有primary,success,warning,danger,error,info六种

深浅有两种:light,dark

深浅级别有六种,light有 3,5,7,8,9,dark只有2

第一个版本我们只先对primary类型进行适配改造

ini 复制代码
const HexToRgb = (defaultStr) => {
    let str = defaultStr.replace('#', '');
    let hxs = str.match(/../g);
    for (let i = 0; i < 3; i++) hxs[i] = parseInt(hxs[i], 16);
    return hxs;
};
// rgb颜色转hex颜色
const RgbToHex = (a, b, c) => {
    let hexs = [a.toString(16), b.toString(16), c.toString(16)];
    for (let i = 0; i < 3; i++) {
        if (hexs[i].length == 1) hexs[i] = '0' + hexs[i];
    }
    return '#' + hexs.join('');
};
// 加深
const darken = (color, level) => {
    let rgbc = HexToRgb(color);
    for (let i = 0; i < 3; i++) {
        rgbc[i] = Math.floor(rgbc[i] * (1 - level));
    }
 
    return RgbToHex(rgbc[0], rgbc[1], rgbc[2]);
};
// 变淡
const lighten = (color, level) => {
    let rgbc = HexToRgb(color);
    for (let i = 0; i < 3; i++) {
        rgbc[i] = Math.floor((255 - rgbc[i]) * level + rgbc[i]);
    }
    return RgbToHex(rgbc[0], rgbc[1], rgbc[2]);
};
 
const setPropertyLightColor = (varName, color, level = 0) => {
    document.body.style.setProperty(varName, lighten(color, level / 10));
 
const setPropertyDarkenColor = (varName, color, level = 1) => {
    document.body.style.setProperty(varName, darken(color, level / 10));
 
const themeColorGradient = (varName, themeColor = '409eff', themeLevel = [3, 5, 7, 8, 9]) => {
    themeLevel.forEach((level) => {
        setPropertyLightColor(varName.replace('#level#', level), themeColor, level);
    });
};
 
// 默认为蓝色#1f67ff
export const setThemeColor = (color = '#1f67ff') => {
    setPropertyLightColor('--el-color-primary', color);
    setPropertyDarkenColor('--el-color-primary-dark-2', color);
    themeColorGradient(`--el-color-primary-light-#level#`, color);
};

2.router.js

javascript 复制代码
import { setThemeColor } from '@/utils/themeUtils.js'; 


router.beforeEach(async (to, from, next) => {
    console.log('====router before ========');
    console.log(to, from);
 
    // 如果不是作为qiankun子应用运行,需要设置主题色
    // 设置新的CSS变量值
    if (!qiankunWindow.__POWERED_BY_QIANKUN__) {
        if (to.query.themeColor) {
            setThemeColor(`#${to.query.themeColor}`);
            const { setColor } = useUserStore();
            setColor(`#${to.query.themeColor}`);
        }
    }
 
    // 跳转前的url有颜色主题,但跳转后的url没有颜色主题,就带上参数
    if (from.query.themeColor && !to.query.themeColor) {
        let newTo = { ...to };
        newTo.query.themeColor = from.query.themeColor;
        next(newTo);
    } else {
        next();
    }
});

变量优先级说明

1.子项目默认在body下写入一套和父框架一样的变量配置

2.如果url中携带themeColor参数,会在body下再写入一次通过自定义算法生成后的颜色变量,覆盖原来在body下的颜色

3.如果需要单独使用变量定制某个颜色,在body下一级的层级添加自定义的颜色变量即可

即 app下变量 > themeColor > body默认变量

效果展示

注意:

a.只能用hex颜色

b.url参数不要带#号,会对vue-router路由对象的参数获取产生干扰

相关推荐
Setsuna_F_Seiei6 小时前
前端转型 Agent 开发 05 之 Agent Hooks 与 Checkpointer(让 Agent 从全自动转变人为可掌控)
前端·agent·ai编程
百万蹄蹄向前冲8 小时前
风扇转了一晚上MVP专家团翻车事故
前端·人工智能
默_笙8 小时前
🏛 给 AI 配一间办公室:Harness Engineering 六大模块与它的实现
前端·javascript
linux_cfan9 小时前
videojs v10 源代码系列解读:14 · 谓词守卫:在运行时安全地调用能力
前端·javascript·音视频
kyriewen9 小时前
我扒了 10,221 条 JD:腾讯技术岗 75% 在要 AI
前端·人工智能·ai编程
郑州光合科技余经理10 小时前
同城外卖小程序开发:下单成功后,后台导出能不能对上用户端状态
开发语言·前端·git·后端·uni-app·php·ai编程
IT_陈寒11 小时前
Vue的响应式让我熬到凌晨三点,原来漏了这个小细节
前端·人工智能·后端
Blanche150011 小时前
利用 RAG 为答疑机器人扩展知识范围
前端
天若有情67311 小时前
【纯前端小工具】公历生日转农历,批量查询每年农历生日对应的公历日期(GitHub Pages在线直接用)
前端·javascript·github pages·农历转换·lunisolar·网页小工具
SoonITer11 小时前
怎样构建一个 Agent-friendly 的网站
前端·agent