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同理 通过这个方法就可以在打包好的文件里面就可以动态换肤了


打包后的效果

浙公网安备 33010602011771号