react,vue 如何打包后动态换肤

在开发过程种,我们碰到有时候已经打包好的项目动态换肤

通过观察发现,在body标签的第一行写入script 里面写入 setcolor 这个函数去实现,document.styleSheets 拿到所有的link引入,如果有href,通过ajax获取css内容字符串,通过replaceAll 方法,整体去替换颜色,再次引入style 从而拿到换肤的目的,由于代码还没走的标签内容,所以不会有样式由原来的样式到新样式过度的问题,而且只是进行了样式重绘

需要mathjs文件

 

<script>
            /**
             * primaryColor 主色,仅支持十六进制
             */
            function setcolor(primaryColor) {
                let bg1 = primaryColor;
                let bg2 = colorutils(primaryColor, 86)
                let bg3 = hexToRgb(bg1);
                // bg1主色,bg2处理的浅色,bg3阴影颜色
                // 前面是要替换的颜色,后面对应替换成什么颜色,因每个项目不一样,改成符合自己项目的即可
                let objcolor = {
                    "#1677ff": bg1,
                    "0 0 0 2px rgba(21,93,158,.2)": bg3,
                    "#3276ab": bg1,
                    "#0a4178": bg1,
                    "#ced9de": bg2,
                    "#78b6ed": bg2,
                    "0 0 0 3px rgba(21,93,158,.12)": bg3,
                    "0 0 0 5px rgba(21,93,158,.12)": bg3,
                    "#c8d4da": bg2,
                    "#78a8c4": bg1,
                    "#a1c1d1": bg2
                }
                // 将颜色变成rgba的方式
                function hexToRgb(hex) {
                    var r, g, b;
                    if (hex.charAt(0) === "#") {
                        hex = hex.substr(1);
                    }
                    r = parseInt(hex.substr(0, 2), 16);
                    g = parseInt(hex.substr(2, 2), 16);
                    b = parseInt(hex.substr(4, 2), 16);
                    return "rgba(" + r + ", " + g + ", " + b + ", .2)";
                }
                // 将颜色变成浅色color颜色opacity 0-100  越靠近0颜色越深越靠近100 颜色越浅
                function colorutils(color, opacity) {
                    function allhsl(color) {
                        if (color.indexOf('rgb') != -1) {
                            var start = color.indexOf('(') + 1;
                            var startval = color.substr(color.indexOf('(') + 1)
                            var end = startval.indexOf(')');
                            var val = startval.substr(0, end)
                            var colorarr = val.split(",");
                            return rgbtohsl(colorarr[0], colorarr[1], colorarr[2])
                        } else {
                            return colorToRgb(color);
                        }
                    }

                    function resultRgb(color, opacity) {
                        var arr = allhsl(color);
                        var result = hsltorgb(arr[0], arr[1], opacity);
                        if (color.indexOf('rgb') != -1) {
                            return "rgb(" + result[0] + "," + result[1] + "," + result[2] + ")";
                        } else {
                            return colorToHex(result);
                        }
                    }

                    function colorToRgb(color) {
                        if (color.indexOf("#") != -1) {
                            color = color.replace("#", "", color)
                        }
                        var color1 = parseInt(color.substr(0, 2), 16);
                        var color2 = parseInt(color.substr(2, 2), 16);
                        var color3 = parseInt(color.substr(4, 2), 16);
                        return rgbtohsl(color1, color2, color3);
                    }

                    function rgbtohsl(r, g, b) {
                        r = math.divide(r, 255);
                        g = math.divide(g, 255);
                        b = math.divide(b, 255);

                        var min = Math.min(r, g, b);
                        var max = Math.max(r, g, b);
                        var l = math.divide(math.add(min, max), 2);
                        var difference = math.subtract(max, min);
                        var h, s, l;
                        if (max == min) {
                            h = 0;
                            s = 0;
                        } else {
                            s = l > 0.5 ? math.divide(difference, math.subtract(math.subtract(2.0, max), min)) : math.divide(
                                difference, math.add(max, min));
                            switch (max) {
                                case r:
                                    h = math.add(math.divide(math.subtract(g, b), difference), (g < b ? 6 : 0));
                                    break;
                                case g:
                                    h = math.add(2.0, math.divide(math.subtract(b, r), difference));
                                    break;
                                case b:
                                    h = math.add(4.0, math.divide(math.subtract(r, g), difference));
                                    break;
                            }
                            h = Math.round(math.multiply(h, 60));
                        }
                        s = Math.round(math.multiply(s, 100));
                        l = Math.round(math.multiply(l, 100));
                        return [h, s, l];
                    }

                    function hsltorgb(h, s, l) {
                        var h = math.divide(h, 360);
                        var s = math.divide(s, 100);
                        var l = math.divide(l, 100);
                        var rgb = [];

                        if (s == 0) {
                            rgb = [Math.round(math.multiply(l, 255)), Math.round(math.multiply(l, 255)), Math.round(math
                                .multiply(l, 255))];
                        } else {
                            var q = l >= 0.5 ? math.subtract(math.add(l, s), math.multiply(l, s)) : math.multiply(l, math.add(1,
                                s));
                            var p = math.subtract(math.multiply(2, l), q);
                            var tr = rgb[0] = math.add(h, math.divide(1, 3));
                            var tg = rgb[1] = h;
                            var tb = rgb[2] = math.subtract(h, math.divide(1, 3));
                            for (var i = 0; i < rgb.length; i++) {
                                var tc = rgb[i];
                                if (tc < 0) {
                                    tc = math.add(tc, 1);
                                } else if (tc > 1) {
                                    tc = math.subtract(tc, 1);
                                }
                                switch (true) {
                                    case (tc < math.divide(1, 6)):
                                        tc = math.add(p, math.multiply(math.multiply(math.subtract(q, p), 6), tc));
                                        break;
                                    case (math.divide(1, 6) <= tc && tc < 0.5):
                                        tc = q;
                                        break;
                                    case (0.5 <= tc && tc < math.divide(2, 3)):
                                        tc = math.add(p, math.multiply(math.subtract(q, p), math.subtract(4, math.multiply(6,
                                            tc))));
                                        break;
                                    default:
                                        tc = p;
                                        break;
                                }
                                rgb[i] = Math.round(math.multiply(tc, 255));
                            }
                        }

                        return rgb;
                    }

                    function colorToHex(color) {
                        function componentToHex(c) {
                            var hex = c.toString(16);
                            return hex.length == 1 ? "0" + hex : hex;
                        }
                        return "#" + componentToHex(color[0]) + componentToHex(color[1]) + componentToHex(color[2]);
                    }
                    return resultRgb(color, opacity)
                }
                // 获取到所有的样式 通过ajax拿到内容做替换,然后在生成style内容放到head标签下
                let styleSheets = document.styleSheets;
                for (let i = 0; i < styleSheets.length; i++) {
                    let obj = styleSheets[i];

                    if (obj && obj.href) {
                        let links = document.querySelectorAll("link");
                        for (let r = 0; r < links.length; r++) {
                            let linknode = links[r];
                            if (linknode.href == obj.href) {
                                linknode.remove()
                            }
                        }
                        const xhr = new XMLHttpRequest();
                        xhr.open('GET', obj.href, false);
                        xhr.send(null);
                        if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
                            let str = xhr.response
                            for (let k in objcolor) {
                                str = str.replaceAll(k, objcolor[k])
                            }
                            let nod = document.createElement('style')
                            nod.type = 'text/css';
                            if (nod.styleSheet) { //ie下
                                nod.styleSheet.cssText = str;
                            } else {
                                nod.innerHTML = str; //或者写成 nod.appendChild(document.createTextNode(str))
                            }
                            document.getElementsByTagName('head')[0].appendChild(nod);
                        }

                    }
                }
            }
            setcolor("#1677ff")
        </script>

vue将上面代码放在body下的第一行,react同理 通过这个方法就可以在打包好的文件里面就可以动态换肤了

 

 

 

 打包后的效果

 

 

posted on 2023-03-14 12:01  Web引领者  阅读(84)  评论(0编辑  收藏  举报