博客视觉魔改

首先在[Blogroot]/source/文件夹下新建两个文件夹cssjs
在两个文件夹下分别创建一个custom.csscustom.js文件。

它们分别存放自定义的CSS和JavaScript代码。

然后在主题配置文件[Blogroot]/_config.butterfly.yml中找到插入外部代码部分,引入custom.csscustom.js

1
2
3
4
5
6
7
8
9
inject:
head:
# - <link rel="stylesheet" href="/xxx.css">
- <link rel="stylesheet" href="/css/custom.css" media="defer" onload="this.media='all'">

bottom:
# - <script src="xxxx"></script>
- <script src="/js/custom.js"></script>
    - <script src="https://cdn.staticfile.org/jquery/3.6.3/jquery.min.js"></script> # jQuery依赖

网站背景一图流

为了使得整个网站从上到下都是一张背景图,我们需要在[Blogroot]/source/css/custom.css中写入如下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/* 页脚与头图透明 */  
#footer {
background: transparent !important;
}
#page-header {
background: transparent !important;
}

/* 白天模式遮罩透明 */
#footer::before {
background: transparent !important;
}
#page-header::before {
background: transparent !important;
}

/* 夜间模式遮罩透明 */
[data-theme="dark"] #footer::before {
background: transparent !important;
}
[data-theme="dark"] #page-header::before {
background: transparent !important;
}

如果之前设置过网站主页的顶图及页脚背景图的,取消设置,避免冗余加载:

1
2
3
4
5
# The banner image of home page  
index_img:

# Footer Background
footer_bg: false

最后,为网站设置一个背景:

1
2
3
4
# 网站背景 #
# 设置图片或背景
# 书写格式 url(http://xxxxxx.com/xxx.jpg)替换为自己想要的图片
background: url(https://tuchuang.voooe.cn/images/2023/11/28/top1.webp)

导航栏魔改

导航栏结构修改:

首先,找到[Blogroot]/themes/butterfly/layout/includes/header/nav.pug,替换其内容如下:

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
nav#nav
//- 导航栏左侧显示LOGO及站名
span#blog-info
a(href=url_for('/') title=config.title)
if theme.nav.logo
img.site-icon(src=url_for(theme.nav.logo))
if theme.nav.display_title
span.site-name=config.title
//- 导航栏中间显示菜单及文章标题
#menus
!=partial('includes/header/menu_item', {}, {cache: true})
center(id="name-container")
//- 假设文章标题是动态设置的,这里仅作为占位符
a(id="page-name" href="javascript:scrollToTop()") 文章标题
//- 导航栏右侧显示搜索按钮
#nav-right
if (theme.algolia_search.enable || theme.local_search.enable || theme.docsearch.enable)
#search-button
a.site-page.social-icon.search(href="javascript:void(0);")
i.fas.fa-search.fa-fw
//- span=' '+_p('search.title')

#toggle-menu
a.site-page(href="javascript:void(0);")
i.fas.fa-bars.fa-fw

导航栏相关样式修改

[Blogroot]/source/css/custom.css中添加如下代码:

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
/* =========== 导航栏魔改 =========== */

/* ------- 导航栏显示调整 ------- */
/* 一级菜单居中 */
#nav {
display: grid;
grid-template-columns: 1fr 2fr 1fr; /* 左中右三列布局 */
align-items: center; /* 纵向居中 */
padding: 0 10px;
}

#blog-info {
text-align: left; /* 确保文字左对齐 */
}
/* 微调logo上下居中 */
.site-icon {
margin-top: -5px
}
#menus {
/* 使 #menus_items 在 #menus 内居中 */
display: flex; /* 使用 Flexbox 在此容器内布局 */
justify-content: center; /* Flexbox 居中对齐 */
align-items: center; /* Flexbox 居中对齐 */
}

#nav-right {
/* 用 Flexbox 确保内容向右对齐 */
display: flex;
justify-content: flex-end; /* 内容靠右 */
}

/* 子菜单横向展示 */
#nav .menus_items .menus_item:hover .menus_item_child {
display: flex !important;
}
/* 这里的2是代表导航栏的第2个元素,即有子菜单的元素,可以按自己需求修改 */
.menus_items .menus_item:nth-child(2) .menus_item_child {
left: -125px;
}
/* 导航栏项目底部蓝色线条动画去除 */
#nav *::after{
background-color: transparent!important;
}

/* 导航栏菜单项字体调整 */
.site-page {
font-size: 0.9em;
font-weight: bold;
}

/* ------- 导航栏显示标题 ------- */
#page-name::before {
font-size: 18px;
position: absolute;
width: 100%;
height: 100%;
border-radius: 8px;
color: white !important;
top: 0;
left: 0;
content: "回到顶部";
background-color: var(--theme-color);
transition: all 0.3s;
-webkit-transition: all 0.3s;
-moz-transition: all 0.3s;
-ms-transition: all 0.3s;
-o-transition: all 0.3s;
opacity: 0;
box-shadow: 0 0 3px var(--theme-color);
line-height: 45px; /*如果垂直位置不居中可以微调此值,也可以删了*/
}
#page-name:hover:before {
opacity: 1;
}
#name-container {
transition: all 0.3s;
-webkit-transition: all 0.3s;
-moz-transition: all 0.3s;
-ms-transition: all 0.3s;
-o-transition: all 0.3s;
}
#name-container:hover {
scale: 1.03;
}
#page-name {
font-weight: bold;
position: relative;
padding: 10px 30px; /*如果文字间隔不合理可以微调修改,第二个是水平方向的padding,第一个是垂直的*/
}
#nav{
padding: 0 20px;
}
/* 移动端不显示标题 */
@media (max-width: 767px) {
#page-name {
display: none;
}
}

导航栏显示逻辑相关:

然后在[Blogroot]/source/js/custom.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
// 导航栏显示标题
document.addEventListener("pjax:complete", tonav);
document.addEventListener("DOMContentLoaded", tonav);
//响应pjax
function tonav() {
document
.getElementById("name-container")
.setAttribute("style", "display:none");
var position = $(window).scrollTop();
$(window).scroll(function () {
var scroll = $(window).scrollTop();
if (scroll > position) {
document.getElementById("name-container").setAttribute("style", "");
document
.getElementsByClassName("menus_items")[1]
.setAttribute("style", "display:none!important");
} else {
document
.getElementsByClassName("menus_items")[1]
.setAttribute("style", "");
document
.getElementById("name-container")
.setAttribute("style", "display:none");
}
position = scroll;
});
// 不在标题显示全局站名
document.getElementById("page-name").innerText =
document.title.split(" | 猫野")[0];
// 在标题显示全局站名
// document.getElementById("page-name").innerText = document.title;
}

function scrollToTop() {
document.getElementsByClassName("menus_items")[1].setAttribute("style", "");
document
.getElementById("name-container")
.setAttribute("style", "display:none");
btf.scrollToDest(0, 500);
}

最后,在主题配置文件[Blogroot]/_config.butterfly.yml中的插入外部代码部分引入[Blogroot]/source/js/custom.js

1
2
3
4
5
  bottom:

    - <script src="/js/custom.js"></script>

    - <script src="https://cdn.staticfile.org/jquery/3.6.3/jquery.min.js"></script> # jQuery依赖

首页魔改

文章双栏展示

原本的首页文章是单栏展示的,如果需要双栏显示,需要安装额外的插件:

1
npm install hexo-maoye-double-article --save

随后在主题配置文件[Blogroot]/_config.burterfly.yml特定元素板块最后添加如下内容:

1
2
3
# 首页双栏显示文章 需安装 hexo-maoye-double-article 插件
article_double_row:
enable: true

[Blogroot]/source/css/custom.css中添加如下内容:

1
2
3
4
5
6
7
8
9
10
/* =========== 首页魔改 =========== */

/* ------- 文章双栏显示,翻页按钮居中 ------- */
#pagination {
width: 100%;
margin: auto;
}
.page-number.current {
background-color: var(--theme-color)!important;
}

元素出场动画

我们可以为首页上文章卡片、侧边栏等添加动画。

在站点配置文件[Blogroot]/_config.yml中添加如下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# wowjs插件,为网页元素添加出场动画
wowjs:
enable: true #控制动画开关。true是打开,false是关闭
priority: 10 #过滤器优先级
mobile: false #移动端是否启用,默认移动端禁用
animateitem:
# 文章栏
- class: recent-post-item #必填项,需要添加动画的元素的class
style: animate__bounceInLeft #必填项,需要添加的动画
# duration: 2s #选填项,动画持续时间,单位可以是ms也可以是s。例如3s,700ms。
# delay: 1s #选填项,动画开始的延迟时间,单位可以是ms也可以是s。例如3s,700ms。
# offset: 100 #选填项,开始动画的距离(相对浏览器底部)
# iteration: 1 #选填项,动画重复的次数
# 侧边栏
- class: card-widget
style: animate__bounceInRight
animate_css: https://npm.elemecdn.com/hexo-butterfly-wowjs/lib/animate.min.css
wow_js: https://npm.elemecdn.com/hexo-butterfly-wowjs/lib/wow.min.js
wow_init_js: https://npm.elemecdn.com/hexo-butterfly-wowjs/lib/wow_init.js

霓虹灯效果

我们可以为网站标题、副标题、文章标题、文章信息等添加霓虹灯效果。

[Blogroot]/source/css/custom.css中添加如下内容:

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
/* ------- 霓虹灯效果 ------- */
/* 日间模式不生效 */
[data-theme="light"] .site-name,
[data-theme="light"] #site-title,
[data-theme="light"] #site-subtitle,
[data-theme="light"] #page-name,
[data-theme="light"] #post-info {
animation: none;
}
/* 夜间模式生效 */
[data-theme="dark"] .site-name,
[data-theme="dark"] #site-title {
animation: light_15px 10s linear infinite;
}
[data-theme="dark"] #site-subtitle {
animation: light_10px 10s linear infinite;
}
[data-theme="dark"] #page-name {
animation: light_10px 10s linear infinite;
}
[data-theme="dark"] #post-info {
animation: light_5px 10s linear infinite;
}
/* 关键帧描述 */
@keyframes light_15px {
0% {
text-shadow: #5636ed 0 0 15px;
}
12.5% {
text-shadow: #11ee5e 0 0 15px;
}
25% {
text-shadow: #f14747 0 0 15px;
}
37.5% {
text-shadow: #f1a247 0 0 15px;
}
50% {
text-shadow: #f1ee47 0 0 15px;
}
50% {
text-shadow: #b347f1 0 0 15px;
}
62.5% {
text-shadow: #002afa 0 0 15px;
}
75% {
text-shadow: #ed709b 0 0 15px;
}
87.5% {
text-shadow: #39c5bb 0 0 15px;
}
100% {
text-shadow: #5636ed 0 0 15px;
}
}

@keyframes light_10px {
0% {
text-shadow: #5636ed 0 0 10px;
}
12.5% {
text-shadow: #11ee5e 0 0 10px;
}
25% {
text-shadow: #f14747 0 0 10px;
}
37.5% {
text-shadow: #f1a247 0 0 10px;
}
50% {
text-shadow: #f1ee47 0 0 10px;
}
50% {
text-shadow: #b347f1 0 0 10px;
}
62.5% {
text-shadow: #002afa 0 0 10px;
}
75% {
text-shadow: #ed709b 0 0 10px;
}
87.5% {
text-shadow: #39c5bb 0 0 10px;
}
100% {
text-shadow: #5636ed 0 0 10px;
}
}

@keyframes light_5px {
0% {
text-shadow: #5636ed 0 0 5px;
}
12.5% {
text-shadow: #11ee5e 0 0 5px;
}
25% {
text-shadow: #f14747 0 0 5px;
}
37.5% {
text-shadow: #f1a247 0 0 15px;
}
50% {
text-shadow: #f1ee47 0 0 5px;
}
50% {
text-shadow: #b347f1 0 0 5px;
}
62.5% {
text-shadow: #002afa 0 0 5px;
}
75% {
text-shadow: #ed709b 0 0 5px;
}
87.5% {
text-shadow: #39c5bb 0 0 5px;
}
100% {
text-shadow: #5636ed 0 0 5px;
}
}

夜间星空背景

我们可以为网站背景添加夜间星空背景。

[Blogroot]/source/css/custom.css中添加如下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/* ------- 黑夜星空背景 ------- */
#universe{
display: block;
position: fixed;
margin: 0;
padding: 0;
border: 0;
outline: 0;
left: 0;
top: 0;
width: 100%;
height: 100%;
pointer-events: none;
/* 这个是调置顶的优先级的,-1在文章页下面,背景上面,个人推荐这种 */
z-index: -1;
}

[Blogroot]/source/js/custom.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
// 黑夜星空背景 
function dark() {
window.requestAnimationFrame =
window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame;
var n,
e,
i,
h,
t = 0.05,
s = document.getElementById("universe"),
o = !0,
a = "180,184,240",
r = "226,225,142",
d = "226,225,224",
c = [];
function f() {
(n = window.innerWidth),
(e = window.innerHeight),
(i = 0.216 * n),
s.setAttribute("width", n),
s.setAttribute("height", e);
}
function u() {
h.clearRect(0, 0, n, e);
for (var t = c.length, i = 0; i < t; i++) {
var s = c[i];
s.move(), s.fadeIn(), s.fadeOut(), s.draw();
}
}
function y() {
(this.reset = function () {
(this.giant = m(3)),
(this.comet = !this.giant && !o && m(10)),
(this.x = l(0, n - 10)),
(this.y = l(0, e)),
(this.r = l(1.1, 2.6)),
(this.dx = l(t, 6 * t) + (this.comet + 1 - 1) * t * l(50, 120) + 2 * t),
(this.dy = -l(t, 6 * t) - (this.comet + 1 - 1) * t * l(50, 120)),
(this.fadingOut = null),
(this.fadingIn = !0),
(this.opacity = 0),
(this.opacityTresh = l(0.2, 1 - 0.4 * (this.comet + 1 - 1))),
(this.do = l(5e-4, 0.002) + 0.001 * (this.comet + 1 - 1));
}),
(this.fadeIn = function () {
this.fadingIn &&
((this.fadingIn = !(this.opacity > this.opacityTresh)),
(this.opacity += this.do));
}),
(this.fadeOut = function () {
this.fadingOut &&
((this.fadingOut = !(this.opacity < 0)),
(this.opacity -= this.do / 2),
(this.x > n || this.y < 0) && ((this.fadingOut = !1), this.reset()));
}),
(this.draw = function () {
if ((h.beginPath(), this.giant))
(h.fillStyle = "rgba(" + a + "," + this.opacity + ")"),
h.arc(this.x, this.y, 2, 0, 2 * Math.PI, !1);
else if (this.comet) {
(h.fillStyle = "rgba(" + d + "," + this.opacity + ")"),
h.arc(this.x, this.y, 1.5, 0, 2 * Math.PI, !1);
for (var t = 0; t < 30; t++)
(h.fillStyle =
"rgba(" +
d +
"," +
(this.opacity - (this.opacity / 20) * t) +
")"),
h.rect(
this.x - (this.dx / 4) * t,
this.y - (this.dy / 4) * t - 2,
2,
2
),
h.fill();
} else
(h.fillStyle = "rgba(" + r + "," + this.opacity + ")"),
h.rect(this.x, this.y, this.r, this.r);
h.closePath(), h.fill();
}),
(this.move = function () {
(this.x += this.dx),
(this.y += this.dy),
!1 === this.fadingOut && this.reset(),
(this.x > n - n / 4 || this.y < 0) && (this.fadingOut = !0);
}),
setTimeout(function () {
o = !1;
}, 50);
}
function m(t) {
return Math.floor(1e3 * Math.random()) + 1 < 10 * t;
}
function l(t, i) {
return Math.random() * (i - t) + t;
}
f(),
window.addEventListener("resize", f, !1),
(function () {
h = s.getContext("2d");
for (var t = 0; t < i; t++) (c[t] = new y()), c[t].reset();
u();
})(),
(function t() {
document.getElementsByTagName("html")[0].getAttribute("data-theme") ==
"dark" && u(),
window.requestAnimationFrame(t);
})();
}
dark();

最后在主题配置文件中引入一个画板,注意先后顺序:

1
2
3
4
5
6
7
8
9
10
11
12
13
inject:

  head:
 
    - <link rel="stylesheet" href="/css/custom.css" media="defer"

  bottom:

+    - <canvas id="universe"></canvas>

    - <script src="/js/custom.js"></script>

    - <script src="https://cdn.staticfile.org/jquery/3.6.3/jquery.min.js"></script> # jQuery依赖

头像呼吸灯

[BlogRoot]/source/css/custom.css中添加如下内容

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
/* 头像呼吸灯 */
[data-theme="light"] .avatar-img {
animation: huxi_light 4s ease-in-out infinite;
}
[data-theme="dark"] .avatar-img {
animation: huxi_dark 4s ease-in-out infinite;
}
@keyframes huxi_light {
0% {
box-shadow: 0px 0px 1px 1px #e9f5fa;
}
50% {
box-shadow: 0px 0px 5px 5px #e9f5fa;
}
100% {
box-shadow: 0px 0px 1px 1px #e9f5fa;
}
}
@keyframes huxi_dark {
0% {
box-shadow: 0px 0px 1px 1px #39c5bb;
}
50% {
box-shadow: 0px 0px 5px 5px #39c5bb;
}
100% {
box-shadow: 0px 0px 1px 1px #39c5bb;
}
}

页面样式魔改

首先在[BlogRoot]/source/css/custom.css中的头部添加如下内容:

1
2
3
4
5
6
7
:root {  
/* 页面透明度、模糊度(亚克力效果) */
--trans-light: rgba(255, 255, 255, 0.6);
--trans-dark: rgba(25, 25, 25, 0.3);
--border-style: 1px solid rgb(169, 169, 169);
--backdrop-filter: blur(5px) saturate(150%);
}

随后在[BlogRoot]/source/css/custom.css中的尾部添加如下内容,设置页面的样式:

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
/* =========== 整站视觉元素魔改 =========== */

/* ------- 页面样式 ------- */
/* 侧边栏个人信息卡片 */
#aside-content > .card-widget.card-info {
background: var(--trans-light);
backdrop-filter: var(--backdrop-filter);
border-radius: 25px;
border: var(--border-style);
}

/* 黑夜模式适配 */
[data-theme="dark"] #aside-content > .card-widget.card-info {
background: var(--trans-dark);
}

/* 首页文章卡片 */
#recent-posts > .recent-post-item {
background: var(--trans-light);
backdrop-filter: var(--backdrop-filter);
border-radius: 25px;
border: var(--border-style);
}

/* 首页侧栏卡片 */
#aside-content .card-widget {
background: var(--trans-light);
backdrop-filter: var(--backdrop-filter);
border-radius: 18px;
border: var(--border-style);
}

/* 文章页、归档页、普通页面 */
div#post,
div#page,
div#archive {
background: var(--trans-light);
backdrop-filter: var(--backdrop-filter);
border: var(--border-style);
border-radius: 20px;
}

/* 导航栏 */
#page-header.nav-fixed #nav {
background: var(--trans-light);
backdrop-filter: var(--backdrop-filter);
}

[data-theme="dark"] #page-header.nav-fixed #nav {
background: rgba(0, 0, 0, 0.3) !important;
}

/* 夜间模式遮罩 */
[data-theme="dark"] #recent-posts > .recent-post-item,
[data-theme="dark"] #aside-content .card-widget,
[data-theme="dark"] div#post,
[data-theme="dark"] div#archive,
[data-theme="dark"] div#page {
background: var(--trans-dark);
}

/* 阅读模式 */
.read-mode #aside-content .card-widget {
background: rgba(158, 204, 171, 0.5) !important;
}
.read-mode div#post {
background: rgba(158, 204, 171, 0.5) !important;
}

/* 夜间模式下的阅读模式 */
[data-theme="dark"] .read-mode #aside-content .card-widget {
background: rgba(25, 25, 25, 0.9) !important;
color: #ffffff;
}
[data-theme="dark"] .read-mode div#post {
background: rgba(25, 25, 25, 0.9) !important;
color: #ffffff;
}

图标魔改

引入自定义图标

参考教程:Iconfont Inject | Akilarの糖果屋

图标准备

首先,去iconfont-阿里巴巴矢量图标库注册登录,搜索自己心仪的图标,然后选择添加入库,加到购物车,在购物车中可以将加购的图标都添加到项目中,可以新建一个blog项目用于存放图标。
随后,到我的项目中打开项目设置,注意勾选彩色,这样可以多彩图标,但是开了这个后,一个项目只能存放40个彩色图标。

图标引入

线上引入方案简单便捷,本地引入方案麻烦些但稳定,看个人选择。我图简单,用的symbol的在线链接引入(iconfont说symbol是今后大流):

在主题配置文件中`[Blogroot]/_config.butterfly.yml中添加Symbol的在线连接:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
inject:

  head:

    # - <link rel="stylesheet" href="/xxx.css">

    - <link rel="stylesheet" href="/css/custom.css" media="defer" onload="this.media='all'">

  bottom:

    # - <script src="xxxx"></script>

    - <canvas id="universe"></canvas>

    - <script src="/js/custom.js"></script>

    - <script src="https://cdn.staticfile.org/jquery/3.6.3/jquery.min.js"></script> # jQuery依赖

+    - <script async src="//at.alicdn.com/t/c/font_4350076_9d1p8d0va1.js"></script>  # symbol方式引入iconfont

随后在[BlogRoot]/source/css/custom.css中添加如下内容,作为引入图标的通用样式:

1
2
3
4
5
6
7
8
/* 多彩图标引入 */
svg.icon {
width: 1.5em;
height: 1.5em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
图标替换
  • 菜单栏图标

找到[Blogroot]/themes/butterfly/layout/includes/header/menu_item.pug替换其中内容:

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
if theme.menu
.menus_items
each value, label in theme.menu
if typeof value !== 'object'
.menus_item
- const valueArray = value.split('||')
a.site-page.faa-parent.animated-hover(href=url_for(trim(value.split('||')[0])))
if valueArray[1]
i.fa-fw(class=trim(valueArray[1]))
- var icon_value = trim(value.split('||')[1])
- var anima_value = value.split('||')[2] ? trim(value.split('||')[2]) : 'faa-tada'
if icon_value.substring(0,2)=="fa"
i.fa-fw(class=icon_value + ' ' + anima_value)
else if icon_value.substring(0,4)=="icon"
svg.icon(aria-hidden="true" class=anima_value,style="height:30px;width:30px;fill:currentColor;position:relative;top:6px")
use(xlink:href=`#`+ icon_value)
span=' '+label
else
.menus_item
- const labelArray = label.split('||')
- const hideClass = labelArray[3] && trim(labelArray[3]) === 'hide' ? 'hide' : ''
a.site-page.group.faa-parent.animated-hover(class=`${hideClass}` href='javascript:void(0);')
if labelArray[1]
- var icon_label = trim(label.split('||')[1])
- var anima_label = label.split('||')[2] ? trim(label.split('||')[2]) : 'faa-tada'
if icon_label.substring(0,2)=="fa"
i.fa-fw(class=icon_label + ' ' + anima_label)
else if icon_label.substring(0,4)=="icon"
svg.icon(aria-hidden="true" class=anima_label,style="height:30px;width:30px;fill:currentColor;position:relative;top:6px")
use(xlink:href=`#`+ icon_label)
span=' '+ trim(labelArray[0])
i.fas.fa-chevron-down
ul.menus_item_child
each val,lab in value
- const valArray = val.split('||')
li
a.site-page.child.faa-parent.animated-hover(href=url_for(trim(val.split('||')[0])))
if valArray[1]
- var icon_val = trim(val.split('||')[1])
- var anima_val = val.split('||')[2] ? trim(val.split('||')[2]) : 'faa-tada'
if icon_val.substring(0,2)=="fa"
i.fa-fw(class=icon_val + ' ' + anima_val)
else if icon_val.substring(0,4)=="icon"
svg.icon(aria-hidden="true" class=anima_val,style="height:30px;width:30px;fill:currentColor;position:relative;top:6px")
use(xlink:href=`#`+ icon_val)
span=' '+ lab
  • 导航栏的搜索图标

找到[Blogroot]/themes/butterfly/layout/includes/header/nav.pug,替换对应的search-button部分:

1
2
3
4
5
6
7
#nav-right
if (theme.algolia_search.enable || theme.local_search.enable || theme.docsearch.enable)
#search-button
a.search.faa-parent.animated-hover(title="检索站内任何你想要的信息")
svg.faa-tada.icon(style="height:30px;width:30px;fill:currentColor;position:relative;top:6px", aria-hidden="true")
use(xlink:href='#icon-sousuo')
//- span=' '+_p('search.title')
  • 个人信息卡片中的社交图标

找到[Blogroot]/themes/butterfly/layout/includes/header/social.pug,替换其内容:

1
2
3
4
5
6
7
8
9
10
each value, title in theme.social
a.social-icon.faa-parent.animated-hover(href=url_for(trim(value.split('||')[0])) target="_blank" title=title === undefined ? '' : trim(title))
if value.split('||')[1]
- var icon_value = trim(value.split('||')[1])
- var anima_value = value.split('||')[2] ? trim(value.split('||')[2]) : 'faa-tada'
if icon_value.substring(0,2)=="fa"
i.fa-fw(class=icon_value + ' ' + anima_value)
else if icon_value.substring(0,4)=="icon"
svg.icon(aria-hidden="true" class=anima_value)
use(xlink:href=`#`+ icon_value)

如此就可以在主题配置文件中设置想要的iconfont图标了:

1
2
3
4
5
social:

  github: https://github.com/fumeng6 || icon-github || faa-tada

  邮箱: mailto:6mengfu@gmail.com || icon-youxiang || faa-tada
  • 侧边栏一系列卡片的图标修改

因为都是一样改法,所以只用一个公告卡片举例。
找到[BlogRoot]/themes/butterfly/layout/includes/widget/card_announcement.pug,替换其内容:

1
2
3
4
5
6
7
8
if theme.aside.card_announcement.enable
.card-widget.card-announcement
.item-headline
a.faa-parent.animated-hover
svg.faa-tada.icon(style="height:25px;width:25px;fill:currentColor;position:relative;top:5px" aria-hidden="true")
use(xlink:href='#icon-wangyuanjing')
span= _p('aside.card_announcement')
.announcement_content!= theme.aside.card_announcement.content

都改了公告卡片的图标,那自然“公告”二字也能改。
找到[BlogRoot]/themes/butterfly/languages/zh-CN.yml(你设置的网站语言是哪个就找哪个),修改对应的文字:

1
2
3
4
5
6
aside:
articles: 归档
tags: 标签
categories: 分类
-  card_announcement: 公告
+  card_announcement: 通知栏

如果想修改其他的侧边栏卡片,基本也是同理。

版权卡片及打赏按钮魔改

在文章页末尾会显示版权信息卡片和打赏按钮,可以根据自己的需求进行修改。

[BlogRoot]/source/css/custom.css中添加如下内容:

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
/* 版权信息卡片美化 */
.post-copyright {
border: 1px solid #ddd; /* 添加边框 */
padding: 15px; /* 添加内边距 */
border-radius: 30px; /* 圆角 */
box-shadow: 0 2px 5px rgba(0,0,0,1); /* 轻微阴影 */
margin-top: 20px; /* 与文章内容留出一些间距 */
}

.post-copyright i {
color: #3498db; /* 改变图标颜色 */
}
.post-copyright-meta, .post-copyright-info {
font-size: 16px; /* 字体大小 */
line-height: 1.5; /* 行高 */
}

.post-copyright a {
color: #3498db; /* 链接颜色 */
text-decoration: none; /* 移除下划线 */
}
.post-copyright a:hover {
text-decoration: underline; /* 鼠标悬停时添加下划线 */
}

.post-copyright {
display: flex;
flex-direction: column; /* 使内容垂直排列 */
gap: 10px; /* 元素间隔 */
}

@media (max-width: 768px) {
/* 在小屏幕设备上的样式调整 */
.post-copyright {
padding: 10px;
font-size: 14px; /* 调整字体大小 */
}
}

/* 打赏区美化 */
/* 美化按钮 */
.reward-button {
padding: 10px 20px; /* 内边距 */
border-radius: 10px; /* 圆角边框 */
margin: 10px 0; /* 上下间距 */
box-shadow: 0 2px 5px rgba(0,0,0,1); /* 轻微阴影 */
transition: background-color 0.3s; /* 过渡动画 */
}

/* 美化二维码展示区域 */
.reward-main {
text-align: center; /* 使二维码居中显示 */
}

.reward-all {
list-style: none; /* 移除列表前的小圆点 */
padding: 0; /* 移除默认的内边距 */
display: inline-block; /* 使列表居中 */
}

.reward-item {
display: inline-block; /* 横向排列 */
margin: 0 10px; /* 两边的间距 */
}

.post-qr-code-img {
width: 200px; /* 设置二维码图片的宽度 */
height: auto; /* 高度自动,保持宽高比 */
border: 1px solid #ddd; /* 图片边框 */
border-radius: 5px; /* 图片圆角 */
box-shadow: 0 2px 5px rgba(0,0,0,0.1); /* 图片阴影 */
}

.post-qr-code-desc {
color: #666; /* 描述文字颜色 */
font-size: 14px; /* 描述文字大小 */
margin-top: 5px; /* 描述文字和图片间距 */
}

网站背景魔改

原本的设定中,背景图片是通过background属性设置的,但这样只能设置一张图片,如果想设置多张图片,可以找到[Blogroot]/themes/butterfly/layout/includes/layout.pug,修改其内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
+    - var DefaultBg = page.defaultbg ? page.defaultbg : theme.background.default
+ - var DDMBg = theme.background.darkmode ? theme.background.darkmode : DefaultBg
+ - var DarkmodeBg = page.darkmodebg ? page.darkmodebg : DDMBg
if theme.background
#web_bg
+ if page.defaultbg || page.darkmodebg
+ style.
+ #web_bg{
+ background: #{DefaultBg} !important;
+ background-attachment: local!important;
+ background-position: center!important;
+ background-size: cover!important;
+ background-repeat: no-repeat!important;
+ }
+ [data-theme="dark"]
+ #web_bg{
+ background: #{DarkmodeBg} !important;
+ background-attachment: local!important;
+ background-position: center!important;
+ background-size: cover!important;
+ background-repeat: no-repeat!important;
+ }

[Blogroot]/themes/butterfly/source/css/_layout目录下新建一个web-bg.styl文件,写入以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$web-bg-night = hexo-config('background.darkmode') ? unquote(hexo-config('background.darkmode')) : $web-bg
$mobile-bg-day = hexo-config('background.mobileday') ? unquote(hexo-config('background.mobileday')) : $web-bg
$mobile-bg-night = hexo-config('background.mobilenight') ? unquote(hexo-config('background.mobilenight')) : $web-bg-night
[data-theme="dark"]
#web_bg
background: $web-bg-night
background-attachment: local
background-position: center
background-size: cover
background-repeat: no-repeat
@media screen and (max-width: 800px)
#web_bg
background: $mobile-bg-day !important
background-attachment: local !important
background-position: center !important
background-size: cover !important
background-repeat: no-repeat !important
[data-theme="dark"]
#web_bg
background: $mobile-bg-night !important
background-attachment: local !important
background-position: center !important
background-size: cover !important
background-repeat: no-repeat !important

然后修改一下[Blogroot]/themes/butterfly/source/css/var.styl中的$web-bg

1
2
-$web-bg = hexo-config('background') && unquote(hexo-config('background'))  
+$web-bg = hexo-config('background.default') && unquote(hexo-config('background.default'))

这样就可以设置多张背景图片了,在主题配置文件[Blogroot]/_config.butterfly.yml中找到background配置项,此时就可以配置四个背景了:

1
2
3
4
5
background: # url(https://tuchuang.voooe.cn/images/2023/11/28/top1.webp)
default: #【必选】默认背景
darkmode: #【可选】PC端夜间模式背景
mobileday: #【可选】移动端日间默认背景
mobilenight: #【可选】移动端夜间模式背景

如果要开pjax,就改一下[Blogroot]/themes/butterfly/layout/includes/third-party/pjax.pug,找到pjaxSelectors,替换为下面的内容:

1
- let pjaxSelectors = ['head > title','#config-diff','#body-wrap','#rightside-config-hide','#rightside-config-show','#web_bg','.js-pjax']

博客功能魔改

标签外挂

  • 插件安装
1
2
3
npm install hexo-butterfly-tag-plugins-plus --save
npm uninstall hexo-renderer-marked --save #与外挂标签语法的兼容性较差,卸载
npm install hexo-renderer-markdown-it --save # 安装这个markdown渲染插件
  • 代码配置
    在站点配置文件[Blogroot]/_config.yml中添加如下内容:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 标签外挂
# tag-plugins-plus
# https://akilar.top/posts/615e2dec/
tag_plugins:
enable: true # 开关
priority: 5 #过滤器优先权,数值越小,执行越早,默认为10,选填
issues: false #issues标签依赖注入开关
link:
placeholder: /img/link.svg #【必选】link卡片外挂标签的默认图标
CDN:
# 【可选】动画标签anima的依赖
anima: https://npm.elemecdn.com/hexo-butterfly-tag-plugins-plus@latest/lib/assets/font-awesome-animation.min.css
# 【可选】issues标签依赖
jquery: # https://npm.elemecdn.com/jquery@latest/dist/jquery.min.js
# 【可选】issues标签依赖
issues: https://npm.elemecdn.com/hexo-butterfly-tag-plugins-plus@latest/lib/assets/issues.js
# 【可选】iconfont标签symbol样式引入,如果不想引入,则设为false
iconfont: false
# 【可选】carousel旋转相册标签鼠标拖动依赖,如果不想引入则设为false
carousel: false
# 【可选】外挂标签样式的CSS依赖,为避免CDN缓存延迟,建议将@latest改为具体版本号
tag_plugins_css: https://npm.elemecdn.com/hexo-butterfly-tag-plugins-plus@latest/lib/tag_plugins.css

PDF显示

  • 插件安装
1
npm install hexo-pdf --save

数学公式显示

  • 插件安装
1
2
3
npm un hexo-renderer-marked --save # 如果有安装这个的话,卸载
npm un hexo-renderer-kramed --save # 如果有安装这个的话,卸载
npm install katex @renbaoshuo/markdown-it-katex #需要安装这个katex插件
  • 代码配置

在主题配置文件[Blogroot]/_config.butterfly.yml的内容设置中找到Math部分,启用katex,并设置per_page参数为false,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Math 数学公式 #
# 关于per_page参数
# 如果将其设置为 true,它将在每个页面中加载 mathjax/katex 脚本 (true 表示每一頁都加載js)
# 如果你将其设置为 false,它将根据你的设置加载 mathjax/katex 脚本(在页面的 front-matter 中添加 'mathjax: true')
# 下面两种工具二选一

# MathJax
mathjax:
enable: false
per_page: false

# KaTeX
katex:
enable: true
per_page: false
hide_scrollbar: true

katex更轻量化,我推荐使用这种来呈现数学公式,上面的内容就是禁用mathjax,启用katex。

最后,在站点配置文件[Blogroot]/_config.yml末尾添加如下内容:

1
2
3
markdown:
plugins:
- '@renbaoshuo/markdown-it-katex'

杂项魔改

导航栏昼夜切换按钮

找到[BlogRoot]/themes/butterfly/layout/includes/header/nav.pug,添加如下内容:

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
nav#nav
//- 导航栏左侧显示LOGO及站名
span#blog-info
a(href=url_for('/') title=config.title)
if theme.nav.logo
img.site-icon(src=url_for(theme.nav.logo))
if theme.nav.display_title
span.site-name=config.title
//- 导航栏中间显示菜单及文章标题
#menus
!=partial('includes/header/menu_item', {}, {cache: true})
center(id="name-container")
//- 假设文章标题是动态设置的,这里仅作为占位符
a(id="page-name" href="javascript:scrollToTop()") 文章标题
//- 导航栏右侧显示搜索按钮
#nav-right
if (theme.algolia_search.enable || theme.local_search.enable || theme.docsearch.enable)
#search-button
a.search.faa-parent.animated-hover(title="检索站内任何你想要的信息")
svg.faa-tada.icon(style="height:30px;width:30px;fill:currentColor;position:relative;top:6px", aria-hidden="true")
use(xlink:href='#icon-sousuo')
//- span=' '+_p('search.title')

+ a.sun_moon.faa-parent.animated-hover(onclick='switchNightMode()', title=_p('rightside.night_mode_title') id="nightmode-button")
+ svg.faa-tada(style="height:30px;width:30px;fill:currentColor;position:relative;top:6px", viewBox='0 0 1024 1024')
+ use#modeicon(xlink:href='#icon-light')

#toggle-menu
a.site-page(href="javascript:void(0);")
i.fas.fa-bars.fa-fw

随后在custom.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
// 日夜切换
function switchNightMode() {
document
.querySelector("body")
.insertAdjacentHTML(
"beforeend",
'<div class="Cuteen_DarkSky"><div class="Cuteen_DarkPlanet"></div></div>'
),
setTimeout(function () {
document.querySelector("body").classList.contains("DarkMode")
? (document.querySelector("body").classList.remove("DarkMode"),
localStorage.setItem("isDark", "0"),
document
.getElementById("modeicon")
.setAttribute("xlink:href", "#icon-light"))
: (document.querySelector("body").classList.add("DarkMode"),
localStorage.setItem("isDark", "1"),
document
.getElementById("modeicon")
.setAttribute("xlink:href", "#icon-dark")),
setTimeout(function () {
document.getElementsByClassName(
"Cuteen_DarkSky"
)[0].style.transition = "opacity 3s";
document.getElementsByClassName("Cuteen_DarkSky")[0].style.opacity =
"0";
setTimeout(function () {
document.getElementsByClassName("Cuteen_DarkSky")[0].remove();
}, 1e3);
}, 2e3);
});
const nowMode =
document.documentElement.getAttribute("data-theme") === "dark"
? "dark"
: "light";
if (nowMode === "light") {
activateDarkMode();
saveToLocal.set("theme", "dark", 2);
GLOBAL_CONFIG.Snackbar !== undefined &&
btf.snackbarShow(GLOBAL_CONFIG.Snackbar.day_to_night);
document.getElementById("modeicon").setAttribute("xlink:href", "#icon-dark");
} else {
activateLightMode();
saveToLocal.set("theme", "light", 2);
document.querySelector("body").classList.add("DarkMode"),
document
.getElementById("modeicon")
.setAttribute("xlink:href", "#icon-light");
}
// handle some cases
typeof utterancesTheme === "function" && utterancesTheme();
typeof FB === "object" && window.loadFBComment();
window.DISQUS &&
document.getElementById("disqus_thread").children.length &&
setTimeout(() => window.disqusReset(), 200);
}

博客加载动画

找到[BlogRoot]/themes/butterfly/layout/includes/loading/fullpage-loading.pug,修改为如下内容:

1
2
3
4
5
6
7
8
9
//- 旋转彩虹 及其显示隐藏js逻辑
#loading-box
.loader
.loader-inner
- var i = 0
while i < 5
.loader-line-wrap
.loader-line
- i++

然后修改[BlogRoot]/themes/butterfly/source/css/_layout/loading.styl中的内容如下:

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
.loader {
background: #000;
background: radial-gradient(#222, #000);
bottom: 0;
left: 0;
overflow: hidden;
position: fixed;
right: 0;
top: 0;
z-index: 99999;
}

.loader-inner {
bottom: 0;
height: 60px;
left: 0;
margin: auto;
position: absolute;
right: 0;
top: 0;
width: 100px;
}

.loader-line-wrap {
animation:
loadspin 2000ms cubic-bezier(.175, .885, .32, 1.275) infinite;
box-sizing: border-box;
height: 50px;
left: 0;
overflow: hidden;
position: absolute;
top: 0;
transform-origin: 50% 100%;
width: 100px;
}
.loader-line {
border: 4px solid transparent;
border-radius: 100%;
box-sizing: border-box;
height: 100px;
left: 0;
margin: 0 auto;
position: absolute;
right: 0;
top: 0;
width: 100px;
}
.loader-line-wrap:nth-child(1) { animation-delay: -50ms; }
.loader-line-wrap:nth-child(2) { animation-delay: -100ms; }
.loader-line-wrap:nth-child(3) { animation-delay: -150ms; }
.loader-line-wrap:nth-child(4) { animation-delay: -200ms; }
.loader-line-wrap:nth-child(5) { animation-delay: -250ms; }

.loader-line-wrap:nth-child(1) .loader-line {
border-color: hsl(0, 80%, 60%);
height: 90px;
width: 90px;
top: 7px;
}
.loader-line-wrap:nth-child(2) .loader-line {
border-color: hsl(60, 80%, 60%);
height: 76px;
width: 76px;
top: 14px;
}
.loader-line-wrap:nth-child(3) .loader-line {
border-color: hsl(120, 80%, 60%);
height: 62px;
width: 62px;
top: 21px;
}
.loader-line-wrap:nth-child(4) .loader-line {
border-color: hsl(180, 80%, 60%);
height: 48px;
width: 48px;
top: 28px;
}
.loader-line-wrap:nth-child(5) .loader-line {
border-color: hsl(240, 80%, 60%);
height: 34px;
width: 34px;
top: 35px;
}

@keyframes loadspin {
0%, 15% {
transform: rotate(0);
}
100% {
transform: rotate(360deg);
}
}
// 控制动画显示与否
#loading-box
&.loaded
.loader
// display: none
// 或者使用opacity和z-index来平滑隐藏
opacity: 0
z-index: -1000
transition: opacity 0.5s ease, z-index 0s 0.5s

最后,在custom.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
// 博客加载动画
document.addEventListener("DOMContentLoaded", function () {
const preloader = {
endLoading: function () {
document.body.style.overflow = "auto";
document.getElementById("loading-box").classList.add("loaded");
},
initLoading: function () {
document.body.style.overflow = "";
document.getElementById("loading-box").classList.remove("loaded");
},
};

if (
document.readyState === "complete" ||
document.readyState === "loaded" ||
document.readyState === "interactive"
) {
preloader.endLoading();
} else {
window.addEventListener("load", preloader.endLoading);
}

// 判断 theme.pjax 和 theme.pjax.enable 的代码需要特别处理,
// 因为这部分逻辑依赖于你的网站配置,可能需要从外部获取这些配置
// 如果你的站点确实使用了PJAX,可以在这里添加相关逻辑
// 这个示例假设你有某种方法来检查 PJAX 是否启用
if (window.theme && window.theme.pjax && window.theme.pjax.enable) {
document.addEventListener("pjax:send", preloader.initLoading);
document.addEventListener("pjax:complete", preloader.endLoading);
}
});

这样,博客加载动画就完成了。