对于提取主题色,看过生成封面图片主色来作为文章封面顶图的文章,了解了许多,但是由于没有备案等,许多东西都没有办法使用,所以之内另寻他路了。无意中看到了一篇帖子是关于这个的,于是便根据这个,加上Heo的教程,便解决了这个问题。

引入工具

在使用这个功能之前,就需要引入js了,其实在GitHub上有许多的关于提取图片主题色的项目,但是好像就rgbaster使用的比较好,对于颜色提取更加准确。这里给出地址,大家可以自行看下。

使用这个我们需要引入js,新建themes/butterfly/source/js/rgbaster.min.js

1
!function(n){"use strict";var t=function(){return document.createElement("canvas").getContext("2d")},e=function(n,e){var a=new Image,o=n.src||n;"data:"!==o.substring(0,5)&&(a.crossOrigin="Anonymous"),a.onload=function(){var n=t("2d");n.drawImage(a,0,0);var o=n.getImageData(0,0,a.width,a.height);e&&e(o.data)},a.src=o},a=function(n){return["rgb(",n,")"].join("")},o=function(n){return n.map(function(n){return a(n.name)})},r=5,i=10,c={};c.colors=function(n,t){t=t||{};var c=t.exclude||[],u=t.paletteSize||i;e(n,function(e){for(var i=n.width*n.height||e.length,m={},s="",d=[],f={dominant:{name:"",count:0},palette:Array.apply(null,new Array(u)).map(Boolean).map(function(){return{name:"0,0,0",count:0}})},l=0;i>l;){if(d[0]=e[l],d[1]=e[l+1],d[2]=e[l+2],s=d.join(","),m[s]=s in m?m[s]+1:1,-1===c.indexOf(a(s))){var g=m[s];g>f.dominant.count?(f.dominant.name=s,f.dominant.count=g):f.palette.some(function(n){return g>n.count?(n.name=s,n.count=g,!0):void 0})}l+=4*r}if(t.success){var p=o(f.palette);t.success({dominant:a(f.dominant.name),secondary:p[0],palette:p})}})},n.RGBaster=n.RGBaster||c}(window);

在你的主题文件中,引入该文件

1
2
3
4
5
6
inject:
head:
# - <link rel="stylesheet" href="">

bottom:
+ - <script src="/js/rgbaster.min.js"></script>

使用

对于使用,就是调用这个js,然后根据提取出来的图片设置博客的主题色就可以了,但是由于图片提取出来的颜色可能会太浅等原因,需要特殊处理下。对于里面的addRule设置变量颜色需要自行去修改。

引入如下自定义js,你可以选择新建一个自定义的js文件,也可以在自己原本的自定义文件中使用。对于引入的文件需要保证在引入上述文件之后引入。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// 封面纯色
function coverColor() {
var path = document.getElementById("post-cover")?.src;
if (path !== undefined) {
RGBaster.colors(path, {
paletteSize: 30,
exclude: ["rgb(255,255,255)", "rgb(0,0,0)", "rgb(254,254,254)"],
success: function (t) {
if (t.dominant != 'rgb(66,90,239)') {
const c = t.dominant.match(/\d+/g);
var value = `rgb(${c[0]},${c[1]},${c[2]})`;
if (getContrastYIQ(colorHex(value)) == "light") {
value = LightenDarkenColor(colorHex(value), -40)
}
document.styleSheets[0].addRule(':root', '--Jay-main:' + value + '!important');
document.styleSheets[0].addRule(':root', '--Jay-main-op:' + value + '23!important');
document.styleSheets[0].addRule(':root', '--Jay-main-op-deep:' + value + 'dd!important');
document.styleSheets[0].addRule(':root', '--Jay-main-none:' + value + '00!important');
Jay.initThemeColor()
document.getElementById("coverdiv").classList.add("loaded");
}
}
});

} else {
document.styleSheets[0].addRule(':root', '--Jay-main: var(--Jay-theme)!important');
document.styleSheets[0].addRule(':root', '--Jay-main-op: var(--Jay-theme-op)!important');
document.styleSheets[0].addRule(':root', '--Jay-main-op-deep:var(--Jay-theme-op-deep)!important');
document.styleSheets[0].addRule(':root', '--Jay-main-none: var(--Jay-theme-none)!important');
Jay.initThemeColor()
}
}

// RGB颜色转化为16进制颜色
function colorHex(str) {
var reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
var that = str;
if (/^(rgb|RGB)/.test(that)) {
var aColor = that.replace(/(?:\(|\)|rgb|RGB)*/g, "").split(",");
var strHex = "#";
for (var i = 0; i < aColor.length; i++) {
var hex = Number(aColor[i]).toString(16);
if (hex === "0") {
hex += hex;
}
strHex += hex;
}
if (strHex.length !== 7) {
strHex = that;
}
return strHex;
} else if (reg.test(that)) {
var aNum = that.replace(/#/, "").split("");
if (aNum.length === 6) {
return that;
} else if (aNum.length === 3) {
var numHex = "#";
for (var i = 0; i < aNum.length; i += 1) {
numHex += (aNum[i] + aNum[i]);
}
return numHex;
}
} else {
return that;
}
}

// 16进制颜色转化为RGB颜色
function colorRgb(str) {
var reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
var sColor = str.toLowerCase();
if (sColor && reg.test(sColor)) {
if (sColor.length === 4) {
var sColorNew = "#";
for (var i = 1; i < 4; i += 1) {
sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1));
}
sColor = sColorNew;
}
// 处理六位的颜色值
var sColorChange = [];
for (var i = 1; i < 7; i += 2) {
sColorChange.push(parseInt("0x" + sColor.slice(i, i + 2)));
}
return "rgb(" + sColorChange.join(",") + ")";
} else {
return sColor;
}
}

// 变暗变亮主方法
function LightenDarkenColor(col, amt) {
var usePound = false;

if (col[0] == "#") {
col = col.slice(1);
usePound = true;
}

var num = parseInt(col, 16);

var r = (num >> 16) + amt;

if (r > 255) r = 255;
else if (r < 0) r = 0;

var b = ((num >> 8) & 0x00FF) + amt;

if (b > 255) b = 255;
else if (b < 0) b = 0;

var g = (num & 0x0000FF) + amt;

if (g > 255) g = 255;
else if (g < 0) g = 0;


return (usePound ? "#" : "") + String("000000" + (g | (b << 8) | (r << 16)).toString(16)).slice(-6);
}

// 判断是否为亮色
function getContrastYIQ(hexcolor) {
var colorrgb = colorRgb(hexcolor);
var colors = colorrgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
var red = colors[1];
var green = colors[2];
var blue = colors[3];
var brightness;
brightness = (red * 299) + (green * 587) + (blue * 114);
brightness = brightness / 255000;
if (brightness >= 0.5) {
return "light";
} else {
return "dark";
}
}
coverColor()

由于此代码是根据本人博客结构实现的,不一定在您的博客上可以生效,如果有什么问题,相信您可以自行调试成功解决。