简介

看到群里大佬优化的页面后终于还是忍不住了,在借鉴大佬的代码上我加了些许改进以更适合我的博客。

总体来说这篇文章是在Butterfly的基础对页面的一些优化,因为涉及到修改源码,所以记录一下修改过程,以免升级主题时产生冲突。

推荐一个魔改教程:Butterfly主题美化教程,里面有大佬们的魔改教学,帮助你取百家之所长,做出好看的博客。PS:主要是我的文章也收录进去了🥰

添加loading动画

原文:Heo同款loading动画 | 安知鱼

修改样式

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
if hexo-config('preloader')
.loading-bg
display: flex;
width: 100%;
height: 100%;
position: fixed;
background: var(--anzhiyu-card-bg);
z-index: 1001;
opacity: 1;
transition: .3s;

#loading-box
.loading-img
width: 100px;
height: 100px;
border-radius: 50%;
margin: auto;
border: 4px solid #f0f0f2;
animation-duration: .3s;
animation-name: loadingAction;
animation-iteration-count: infinite;
animation-direction: alternate;
.loading-image-dot
width: 30px;
height: 30px;
background: #6bdf8f;
position: absolute;
border-radius: 50%;
border: 6px solid #fff;
top: 50%;
left: 50%;
transform: translate(18px, 24px);
&.loaded
.loading-bg
opacity: 0;
z-index: -1000;

@keyframes loadingAction
0% {
opacity: 1;
}

100% {
opacity: .4;
}

修改结构

themes/butterfly/layout/includes/loading/loading.pug替换为以下代码:

1
2
3
4
#loading-box(onclick='document.getElementById("loading-box").classList.add("loaded")')
.loading-bg
div.loading-img
.loading-image-dot

添加自定义 css

在合适的地方加上自定义 css,url换成自己的头像即可:

1
2
3
4
.loading-img {
background: url(https://blog.aqcoder.cn/img/avatar.png) no-repeat center center;
background-size: cover;
}

添加顶部加载条

原文:为你的Butterfly添加顶部加载进度条 | Xlenco

添加自定义 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
.pace {
pointer-events: none;
user-select: none;
z-index: 2;
position: fixed;
margin: auto;
top: 4px;
left: 0;
right: 0;
height: 8px;
border-radius: 8px;
width: 6rem;
background: #eaecf2;
overflow: hidden;
}

.pace-inactive .pace-progress {
opacity: 0;
transition: 0.3s ease-in;
}

.pace.pace-inactive {
opacity: 0;
transition: 0.3s;
top: -8px;
}

.pace .pace-progress {
box-sizing: border-box;
transform: translate3d(0, 0, 0);
position: fixed;
z-index: 2;
display: block;
position: absolute;
top: 0;
right: 100%;
height: 100%;
width: 100%;
background: #49b1f5;
background: linear-gradient(to right,
rgb(18, 194, 233),
rgb(196, 113, 237),
rgb(246, 79, 89));
animation: gradient 2s ease infinite;
background-size: 200%;
}

引入 JS

可在配置文件_config.butterfly.ymlhead添加:

1
2
3
inject:
head:
- <script src="//cdn.bootcss.com/pace/1.0.2/pace.min.js"></script>

魔改导航栏样式

原文:关于Butterfly的导航栏的一些教程 Ariasakaの小窝

分离搜索栏与菜单栏

修改[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
nav#nav
span#blog_name
a#site-name(href=url_for('/')) #[=config.title]

#menus
- if (theme.algolia_search.enable || theme.local_search.enable)
- #search-button
- a.site-page.social-icon.search
- i.fas.fa-search.fa-fw
- span=' '+_p('search.title')
!=partial('includes/header/menu_item', {}, {cache: true})
#nav-right
+ if (theme.algolia_search.enable || theme.local_search.enable)
+ #search-button
+ a.site-page.social-icon.search
+ i.fas.fa-search.fa-fw
- #toggle-menu
- a.site-page
- i.fas.fa-bars.fa-fw
+ #toggle-menu
+ a.site-page
+ i.fas.fa-bars.fa-fw

导航栏居中

自定义css:

1
2
3
4
5
6
7
#nav-right{
flex:1 1 auto;
justify-content: flex-end;
margin-left: auto;
display: flex;
flex-wrap:nowrap;
}

去掉导航栏项目底下的蓝色长条

1
2
3
#nav *::after{
background-color: transparent!important;
}

子菜单横向布局

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
.menus_item_child li:not(#sidebar-menus li){
float: left;
border-radius: 6px!important;
-webkit-border-radius: 6px!important;
-moz-border-radius: 6px!important;
-ms-border-radius: 6px!important;
-o-border-radius: 6px!important;
}
.menus_item_child:not(#sidebar-menus ul){
/*
left:calc(-150%)!important;这是估算值,为了保持元素居中的,如果不合适可以自己调
在网友的建议下,改为:*/
left:50%;
translate:-50%;
}

网站标题部分的增强版

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
#site-name::before{
opacity: 0;
background-color: var(--lyx-theme)!important;
border-radius: 8px;
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
-ms-border-radius: 8px;
-o-border-radius: 8px;
transition: .3s;
-webkit-transition: .3s;
-moz-transition: .3s;
-ms-transition: .3s;
-o-transition: .3s;
position:absolute;
top:0!important;
right:0!important;
width:100%;
height:100%;
content: "\f015";
box-shadow: 0 0 5px var(--lyx-theme);
font-family: "Font Awesome 6 Free";
text-align: center;
color:white;
line-height:34px;/*如果有溢出或者垂直不居中的现象微调一下这个参数*/
font-size: 18px;/*根据个人喜好*/
}
#site-name:hover::before{
opacity: 1;
scale:1.03;
}
#site-name{
position: relative;
font-size: 24px; /*一定要把字体调大点,否则效果惨不忍睹!*/
}
:root{
--lyx-theme:#ed709b /*我的主题色*/
}

顶栏常驻

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.nav-fixed #nav{
transform: translateY(58px)!important;
-webkit-transform: translateY(58px)!important;
-moz-transform: translateY(58px)!important;
-ms-transform: translateY(58px)!important;
-o-transform: translateY(58px)!important;
}
#nav{
transition: none!important;
-webkit-transition: none!important;
-moz-transition: none!important;
-ms-transition: none!important;
-o-transition: none!important;
}

显示标题

修改[blogRoot]\themes\Butterfly\layout\includes\header\nav.pug

1
2
3
4
5
6
7
8
9
10
nav#nav
span#blog_name
a#site-name(href=url_for('/')) #[=config.title]

#menus
!=partial('includes/header/menu_item', {}, {cache: true})
+ center(id="name-container")
+ a(id="page-name" href="javascript:scrollToTop()") PAGE_NAME
...

然后添加nav.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
//js有一个小问题:就是只要鼠标滚动不论哪里都会响应,即便你滚动的是子元素

//2022.9.11 已修复,需要jq,请自行引入
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;

});
function scrollToTop(){
document.getElementsByClassName("menus_items")[1].setAttribute("style","");
document.getElementById("name-container").setAttribute("style","display:none");
btf.scrollToDest(0, 500);
}
//修复没有弄右键菜单的童鞋无法回顶部的问题
document.getElementById("page-name").innerText = document.title.split(" | Ariasakaの小窝")[0];
/*这里是去掉你的网站全局名称的设置,如果你不需要去掉,你可以写成:
document.getElementById("page-name").innerText=document.title

或者把你的网站的分隔符和全局网站名称加上去*/

最后添加如下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
#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(--lyx-theme);
transition: all .3s;
-webkit-transition: all .3s;
-moz-transition: all .3s;
-ms-transition: all .3s;
-o-transition: all .3s;
opacity: 0;
box-shadow: 0 0 3px var(--lyx-theme);
line-height: 45px; /*如果垂直位置不居中可以微调此值,也可以删了*/
}
#page-name:hover:before{
opacity: 1;
}
#name-container{
transition: all .3s;
-webkit-transition: all .3s;
-moz-transition: all .3s;
-ms-transition: all .3s;
-o-transition: all .3s;
}
#name-container:hover{
scale:1.03
}
#page-name{
position: relative;
padding:10px 30px/*如果文字间隔不合理可以微调修改,第二个是水平方向的padding,第一个是垂直的*/
}

展示首页文章分类

冰老师的方案一:

冰老师的首页文章分类

原文:教程:hexo-magnet 插件 1.0 | 小冰博客

冰老师的方案二:

image-20221027230449107

原文:Categories Magnet | Akilarの糖果屋

npm安装

1
npm install hexo-butterfly-categories-card --save

在站点配置文件_config.yml配置:

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
# 文章分类磁贴
# hexo-butterfly-categories-card
# see https://akilar.top/posts/a9131002/
categoryBar:
enable: true # 开关
priority: 5 #过滤器优先权
enable_page: / # 应用页面
layout: # 挂载容器类型
type: id
name: recent-posts
index: 0
column: odd # odd:3列 | even:4列
row: 1 #显示行数,默认两行,超过行数切换为滚动显示
message:
- descr: 记录搭建过程
cover: /img/category-card-bg/Scooter.png
- descr: 详细教程讲解
cover: /img/category-card-bg/Hydrogen.png
- descr: 记录学习历程
cover: /img/category-card-bg/VisionsofGrandur.png
- descr: 分享博客收获
cover: /img/category-card-bg/Relaxingred.png
- descr: 学习精辟思路
cover: /img/category-card-bg/SublimeLight.png
- descr: 分享日常生活
cover: /img/category-card-bg/TaranTado.png
custom_css: https://npm.elemecdn.com/hexo-butterfly-categories-card@1.0.0/lib/categorybar.css

注意图片更换为自己的图片链接

魔改文章分类

魔改文章分类

参考原文:

Butterfly魔改:动态分类条,可以根据页面变化而改变的分类列表展示方式 | 张洪Heo

Hexo博客 | 动态分类标签条,自动获取全站分类与标签进行展示 | Justlovesmile’s BLOG

新建PUG文件

首先是分类条,在themes/butterfly/layout/includes/处新建文件categoryBar.pug

1
2
3
4
#category-bar
.category-bar-items#category-bar-items
!=getarray_bar("category")
a.category-bar-more(href="/categories/") 更多

其次是标签条,在themes/butterfly/layout/includes/处新建文件tagBar.pug,因为样式一样,所以没有更改id和class名称:

1
2
3
4
#category-bar
.category-bar-items#category-bar-items
!=getarray_bar("tag")
a.category-bar-more(href="/tags/") 更多

新建Hexo辅助函数

theme/butterfly/scripts/helpers/中创建get_arrays.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
hexo.extend.helper.register('getarray_bar', function (types) {
if (!types) {
types = "category"
}
const categoriesBar = function (categories) {
if (!categories || !categories.length) return ``
const categoryArr = []
hexo.locals.get('categories').map(function (category) {
categoryArr.push({ name: category.name, value: category.length })
})
categoryArr.sort((a, b) => { return b.value - a.value })
let strCategoriesBar = ``
for (let i = 0; i < categories.length; i++) {
strTemp=`
<div class="category-bar-item" id="${categoryArr[i].name}">
<a href="/categories/${categoryArr[i].name}/">${categoryArr[i].name}</a>
</div>`
strCategoriesBar+=strTemp
}
return strCategoriesBar
}
const tagsBar = function(tags) {
if (!tags || !tags.length) return ``
const tagArr = []
hexo.locals.get('tags').map(function (tag) {
tagArr.push({ name: tag.name, value: tag.length })
})
tagArr.sort((a, b) => { return b.value - a.value })
let strTagsBar = ``
for (let i = 0; i < tags.length; i++) {
strTemp=`
<div class="category-bar-item" id="${tagArr[i].name}">
<a href="/tags/${tagArr[i].name}/">${tagArr[i].name}</a>
</div>`
strTagsBar+=strTemp
}
return strTagsBar
}
if (types == "category"){
return categoriesBar(this.site.categories)
}
if (types == "tag"){
return tagsBar(this.site.tags)
}
})

引用模块

在分类页面引用:找到theme/butterfly/layout/category.pug

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
extends includes/layout.pug

block content
if theme.category_ui == 'index'
include ./includes/mixins/post-ui.pug
#recent-posts.recent-posts.category_ui
+postUI
include includes/pagination.pug
else
include ./includes/mixins/article-sort.pug
#category
+ .category-in-bar
+ .category-in-bar-tips
+ i.fa-fw.fas.fa-folder-open
+ include includes/categoryBar.pug
.article-sort-title= _p('page.category') + ' - ' + page.category
+articleSort(page.posts)
include includes/pagination.pug

在标签页引用:找到theme/butterfly/layout/tag.pug

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
extends includes/layout.pug

block content
if theme.tag_ui == 'index'
include ./includes/mixins/post-ui.pug
#recent-posts.recent-posts
+postUI
include includes/pagination.pug
else
include ./includes/mixins/article-sort.pug
#tag
+ .category-in-bar
+ .category-in-bar-tips
+ i.fa-fw.fas.fa-tags
+ include includes/tagBar.pug
.article-sort-title= _p('page.tag') + ' - ' + page.tag
+articleSort(page.posts)
include includes/pagination.pug

引入js和css文件

引入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
//分类条
function categoriesBarActive() {
var urlinfo = window.location.pathname;
urlinfo = decodeURIComponent(urlinfo)
console.log(urlinfo);
//判断是否是首页
if (urlinfo == '/') {
if (document.querySelector('#category-bar')) {
document.getElementById('主页').classList.add("select")
}
} else {
// 验证是否是分类链接
var pattern = /\/categories\/.*?\//;
var patbool = pattern.test(urlinfo);
// 获取当前的分类
if (patbool) {
var valuegroup = urlinfo.split("/");
// 获取当前分类
var nowCategorie = valuegroup[2];
if (document.querySelector('#category-bar')) {
document.getElementById(nowCategorie).classList.add("select");
}
}
}
}

//鼠标控制横向滚动
function topCategoriesBarScroll() {
if (document.getElementById("category-bar-items")) {
let xscroll = document.getElementById("category-bar-items");
xscroll.addEventListener("mousewheel", function (e) {
//计算鼠标滚轮滚动的距离
let v = -e.wheelDelta / 2;
xscroll.scrollLeft += v;
//阻止浏览器默认方法
e.preventDefault();
}, false);
}
}


//标签条
function tagsBarActive() {
var urlinfo = window.location.pathname;
urlinfo = decodeURIComponent(urlinfo)
//console.log(urlinfo);
//判断是否是首页
if (urlinfo == '/') {
if (document.querySelector('#tags-bar')) {
document.getElementById('首页').classList.add("select")
}
} else {
// 验证是否是分类链接
var pattern = /\/tags\/.*?\//;
var patbool = pattern.test(urlinfo);
//console.log(patbool);
// 获取当前的标签
if (patbool) {
var valuegroup = urlinfo.split("/");
//console.log(valuegroup[2]);
// 获取当前分类
var nowTag = valuegroup[2];
if (document.querySelector('#category-bar')) {
document.getElementById(nowTag).classList.add("select");
}
}
}
}
categoriesBarActive()
topCategoriesBarScroll()
tagsBarActive()

引入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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162

:root {
--heo-white: #fff;
--heo-black: #000;
--heo-none: rgba(0, 0, 0, 0);
--heo-gray: #999999;
--heo-yellow: #ffc93e;
--heo-main: var(--heo-theme);
--heo-main-op: var(--heo-theme-op);
--heo-shadow-theme: 0 8px 12px -3px var(--heo-theme-op);
--heo-shadow-main: 0 8px 12px -3px var(--heo-main-op);
--heo-shadow-blue: 0 8px 12px -3px rgba(40, 109, 234, .20);
--heo-shadow-white: 0 8px 12px -3px rgba(255, 255, 255, .20);
--heo-shadow-black: 0 0 12px 4px rgba(0, 0, 0, .05);
--heo-shadow-yellow: 0px 38px 77px -26px rgba(255, 201, 62, .12);
--heo-shadow-red: 0 8px 12px -3px #ee7d7936;
--heo-shadow-green: 0 8px 12px -3px #87ee7936;
--heo-logo-color: linear-gradient(215deg, #4584ff 30%, #ff7676 70%);
--style-border: 1px solid var(--heo-card-border);
--style-border-hover: 1px solid var(--heo-theme);
}

::selection {
background: var(--heo-fontcolor);
color: var(--heo-background);
}

[data-theme=light] {
--heo-theme: #425AEF;
--heo-theme-op: #4259ef23;
--heo-blue: #425AEF;
--heo-red: #D8213C;
--heo-pink: #FF7C7C;
--heo-green: #57bd6a;
--heo-fontcolor: #363636;
--heo-background: #f7f9fe;
--heo-reverse: #000;
--heo-maskbg: rgba(255, 255, 255, 0.6);
--heo-maskbgdeep: rgba(255, 255, 255, 0.85);
--heo-hovertext: var(--heo-theme);
--heo-ahoverbg: #F7F7FA;
--heo-lighttext: var(--heo-main);
--heo-secondtext: rgba(60, 60, 67, 0.6);
--heo-scrollbar: rgba(60, 60, 67, 0.4);
--heo-card-btn-bg: #edf0f7;
--heo-post-blockquote-bg: #fafcff;
--heo-post-tabs-bg: #f2f5f8;
--heo-secondbg: #edf0f7;
--heo-shadow-nav: 0 5px 12px -5px rgba(102, 68, 68, 0.05);
--heo-card-bg: #fff;
--heo-shadow-lightblack: 0 5px 12px -5px rgba(102, 68, 68, 0.00);
--heo-shadow-light2black: 0 5px 12px -5px rgba(102, 68, 68, 0.00);
--heo-card-border: #e3e8f7;
}

[data-theme=dark] {
--heo-theme: #0084FF;
--heo-theme-op: #0084FF23;
--heo-blue: #0084FF;
--heo-red: #FF3842;
--heo-pink: #FF7C7C;
--heo-green: #57bd6a;
--heo-fontcolor: #F7F7FA;
--heo-background: #18171d;
--heo-reverse: #fff;
--heo-maskbg: rgba(0, 0, 0, 0.6);
--heo-maskbgdeep: rgba(0, 0, 0, 0.85);
--heo-hovertext: #0A84FF;
--heo-ahoverbg: #fff;
--heo-lighttext: #f2b94b;
--heo-secondtext: #a1a2b8;
--heo-scrollbar: rgba(200, 200, 223, 0.4);
--heo-card-btn-bg: #30343f;
--heo-post-blockquote-bg: #000;
--heo-post-tabs-bg: #121212;
--heo-secondbg: #30343f;
--heo-shadow-nav: 0 5px 20px 0px rgba(28, 28, 28, 0.4);
--heo-card-bg: #1d1b26;
--heo-shadow-lightblack: 0 5px 12px -5px rgba(102, 68, 68, 0.0);
--heo-shadow-light2black: 0 5px 12px -5px rgba(102, 68, 68, 0.0);
--heo-card-border: #42444a;
}

@media screen and (max-width: 768px) {
:root {
--style-border: 0px solid var(--heo-card-border);
--style-border-hover: 0px solid var(--heo-theme);
}
}


/* 首页分类条展示 */
#category-bar {
padding: 0.4rem 1rem 0.4rem 0.5rem;
background: #FFFFFF;
border-radius: 8px;
box-shadow: var(--card-box-shadow);
display: flex;
white-space: nowrap;
overflow: hidden;
/* margin-bottom: 1rem; */
margin-top: 1rem;
}

@media screen and (max-width: 768px) {
#category-bar {
border-radius: 0;
}
}

#category #category-bar {
padding: 0;
border: none;
}

#category a.category-bar-item.select a {
display: none;
}

.category-in-bar {
display: flex;
white-space: nowrap;
}

.category-in-bar-tips {
margin-right: 1rem;
}

.category-bar-items {
white-space: nowrap;
overflow-x: scroll;
display: flex;
}

.category-bar-items::-webkit-scrollbar {
display: none;
}

.category-bar-item a {
padding: 0.1rem 1rem;
margin: 0 0.25rem;
font-weight: bold;
border-radius: 12px;
color: #363636;
}

.category-bar-item:hover a {
background: var(--heo-main);
color: var(--heo-white);
}

.category-bar-item.select a {
background: var(--heo-main);
color: var(--heo-white);
border-radius: 8px;
}

.category-bar-more {
margin-left: 1rem;
font-weight: bold;
color: #363636;
}

记录一次因为pjax导致js无法生效以及解决方案 | aqcoder

添加文章置顶

原主题置顶方案:

原主题置顶方案

设置方法参考Butterfly博客主题搭建系列:基础教程 | aqcoder

这种方法会有一个缺陷:当置顶文章过多导致一页都置顶文章,观感不好,可参考:教程:hexo-swiper 文章置顶插件 | 小冰博客

完成效果预览:

文章置顶效果

npm安装插件

1
npm install hexo-butterfly-swiper --save

在网站根目录_config.yml新增配置项:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# hexo-butterfly-swiper
# see https://akilar.top/posts/8e1264d1/
swiper:
enable: true # 开关
priority: 5 #过滤器优先权
enable_page: all # 应用页面
timemode: date #date/updated
layout: # 挂载容器类型
type: id
name: recent-posts
index: 0
default_descr: 再怎么看我也不知道怎么描述它的啦!
swiper_css: https://npm.elemecdn.com/hexo-butterfly-swiper/lib/swiper.min.css #swiper css依赖
swiper_js: https://npm.elemecdn.com/hexo-butterfly-swiper/lib/swiper.min.js #swiper js依赖
custom_css: https://npm.elemecdn.com/hexo-butterfly-swiper/lib/swiperstyle.css # 适配主题样式补丁
custom_js: https://npm.elemecdn.com/hexo-butterfly-swiper/lib/swiper_init.js # swiper初始化方法
参数备选值/类型释义
prioritynumber【可选】过滤器优先级,数值越小,执行越早,默认为10,选填
enabletrue/false【必选】控制开关
enable_pagepath/all【可选】填写想要应用的页面的相对路径(即路由地址),如根目录就填’/‘,分类页面就填’/categories/‘。若要应用于所有页面,就填’all’,默认为all
timemodedate/updated【可选】时间显示,date为显示创建日期,updated为显示更新日期,默认为date
layout.typeid/class【可选】挂载容器类型,填写id或class,不填则默认为id
layout.nametext【必选】挂载容器名称
layout.index0和正整数【可选】前提是layout.type为class,因为同一页面可能有多个class,此项用来确认究竟排在第几个顺位
default_descrtext默认文章描述
swiper_cssurl【可选】自定义的swiper依赖项css链接
swiper_jsurl【可选】自定义的swiper依赖项加js链接
custom_cssurl【可选】适配主题样式补丁
custom_jsurl【可选】swiper初始化方法

使用方法

在文章的front_matter中添加swiper_index配置项即可。

1
2
3
4
5
6
7
8
---
title: 文章标题
date: 创建日期
updated: 更新日期
cover: 文章封面
description: 文章描述
swiper_index: 1 #置顶轮播图顺序,非负整数,数字越大越靠前
---

文章双栏

文章双栏

原文:教程:butterfly 主题文章双栏布局插件 | 小冰博客

npm安装

1
npm i hexo-butterfly-article-double-row --save

新增网站根目录_config.yml 配置项:

1
2
butterfly_article_double_row:
enable: true

魔改分类页面

分类页面

原文:hexo博客butterfly主题美化css大礼包 | space of Lee !

自定义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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183

/* 分类页面样式 */
#page .category-lists .category-list .category-list-item {
position: relative;
display: inline-block;
padding: 0 1rem;
width: 48%;
font-weight: 700;
margin: 0 0.5% 2% 0.5%;
border-radius: var(--border-radius);
-webkit-box-shadow: rgb(50 50 50 / 30%) 50px 50px 50px 50px inset;
box-shadow: rgb(50 50 50 / 30%) 50px 50px 50px 50px inset;
border-radius: 8px;
}

@media (max-width: 640px) {
#page .category-lists .category-list .category-list-item {
width: 95%;
border-radius: 8px;
margin-top: 3px;
}
}

#page .category-lists .category-list .category-list-item::before {
display: none;
}

#page .category-lists .category-list .category-list-item .category-list-link {
color: #fff;
font-size: 1.5rem;
margin-left: 0.4rem;
}

#page .category-lists .category-list .category-list-item .category-list-link::after {
content: "";
position: relative;
width: 0;
bottom: 0;
display: block;
height: 3px;
border-radius: 3px;
background: #fff;
}

#page .category-lists .category-list .category-list-item .category-list-link:hover::after {
width: 60%;
left: 1%;
-webkit-transition: all 0.6s;
-moz-transition: all 0.6s;
-o-transition: all 0.6s;
-ms-transition: all 0.6s;
transition: all 0.6s;
}

#page .category-lists .category-list .category-list-item .category-list-count {
color: #fff;
font-size: 1.3rem;
}

#page .category-lists .category-list .category-list-item .category-list-count::before {
content: "\f02d";
padding-right: 15px;
font-family: "Font Awesome 6 Free";
}

/* #page .category-list-count::before, */
#page .category-list-count::after {
display: none;
}

#page .category-lists .category-list li.category-list-item a.category-list-link::before {
position: absolute;
font-size: 4rem;
line-height: 4rem;
top: 1rem;
right: 1rem;
border-radius: 8px;
transform: rotate(-15deg);
-ms-transform: rotate(-15deg);
-moz-transform: rotate(-15deg);
-webkit-transform: rotate(-15deg);
-o-transform: rotate(-15deg);
-webkit-transition: all 0.6s;
-moz-transition: all 0.6s;
-o-transition: all 0.6s;
-ms-transition: all 0.6s;
transition: all 0.6s;
}

#page .category-lists .category-list li.category-list-item a.category-list-link:hover::before {
opacity: 0.9;
transform: rotate(0);
-ms-transform: rotate(0);
-moz-transform: rotate(0);
-webkit-transform: rotate(0);
-o-transform: rotate(0);
}

/* 优秀文章 */
#page .category-lists .category-list li.category-list-item:nth-child(1) {
background: #4074f6;
background: -webkit-linear-gradient(to right, #667db6, #0082c8, #0082c8, #667db6);
}

#page .category-lists .category-list li.category-list-item:nth-child(1) a.category-list-link::before {
content: "📑";
}

/* 博客总结 */
#page .category-lists .category-list li.category-list-item:nth-child(2) {
background: -webkit-linear-gradient(left, #ba52ed, #ff99fe);
background: -moz-linear-gradient(left, #ba52ed, #ff99fe);
background: -o-linear-gradient(left, #ba52ed, #ff99fe);
background: -ms-linear-gradient(left, #ba52ed, #ff99fe);
background: linear-gradient(to right, #ba52ed, #ff99fe);
}

#page .category-lists .category-list li.category-list-item:nth-child(2) a.category-list-link::before {
content: "📚";
}

/* 博客搭建 */
#page .category-lists .category-list li.category-list-item:nth-child(3) {
background: -webkit-linear-gradient(left, #6639a6, #3490de);
background: -moz-linear-gradient(left, #6639a6, #3490de);
background: -o-linear-gradient(left, #6639a6, #3490de);
background: -ms-linear-gradient(left, #6639a6, #3490de);
background: linear-gradient(to right, #6639a6, #3490de);
}

#page .category-lists .category-list li.category-list-item:nth-child(3) a.category-list-link::before {
content: "🦋";
}

#page .category-lists .category-list li.category-list-item:nth-child(4) {
background: -webkit-linear-gradient(right, #38ef7d, #11998e);
background: -moz-linear-gradient(right, #38ef7d, #11998e);
background: -o-linear-gradient(right, #38ef7d, #11998e);
background: -ms-linear-gradient(right, #38ef7d, #11998e);
background: linear-gradient(to left, #38ef7d, #11998e);
}

#page .category-lists .category-list li.category-list-item:nth-child(4) a.category-list-link::before {
content: "📔";
}

/* 实用教程 */
#page .category-lists .category-list li.category-list-item:nth-child(5) {
background: -webkit-linear-gradient(left, #b91d73, #f953c6);
background: -moz-linear-gradient(left, #b91d73, #f953c6);
background: -o-linear-gradient(left, #b91d73, #f953c6);
background: -ms-linear-gradient(left, #b91d73, #f953c6);
background: linear-gradient(to right, #b91d73, #f953c6);
}

#page .category-lists .category-list li.category-list-item:nth-child(5) a.category-list-link::before {
content: "✨";
}
/* 敲敲代码 */
#page .category-lists .category-list li.category-list-item:nth-child(6) {
background: -webkit-linear-gradient(left, #f12711, #f5af19);
background: -moz-linear-gradient(left, #f12711, #f5af19);
background: -o-linear-gradient(left, #f12711, #f5af19);
background: -ms-linear-gradient(left, #f12711, #f5af19);
background: linear-gradient(to right, #f12711, #f5af19);
}

#page .category-lists .category-list li.category-list-item:nth-child(6) a.category-list-link::before {
content: "💻";
}

/* 生活杂谈 */
#page .category-lists .category-list li.category-list-item:nth-child(7) {
background: -webkit-linear-gradient(left, #009ad6, #1b315e);
background: -moz-linear-gradient(left, #009ad6, #1b315e);
background: -o-linear-gradient(left, #009ad6, #1b315e);
background: -ms-linear-gradient(left, #009ad6, #1b315e);
background: linear-gradient(to right, #009ad6, #1b315e);
}

#page .category-lists .category-list li.category-list-item:nth-child(7) a.category-list-link::before {
content: "💬";
}

魔改标签页面

魔改标签页面

原文:Hexo博客标签的魔改 | Leonus

修改butterfly\scripts\helpers\page.js文件:

如果你只是想添加一个数量的话,在第52行的${tag.name}后增加 (${tag.length}),如下:

1
result += `<a href="${env.url_for(tag.path)}" style="${style}">${tag.name} (${tag.length})</a>`

如果你不想要字体有大有小的话,可以采用css + !important的方法,也可以选择删除如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 需要删除的
const minfontsize = options.minfontsize
const maxfontsize = options.maxfontsize
const unit = options.unit || 'px'
const sizes = []
source.sort('length').forEach(tag => {
const { length } = tag
if (sizes.includes(length)) return
sizes.push(length)
})
const length = sizes.length - 1
const ratio = length ? sizes.indexOf(tag.length) / length : 0
const size = minfontsize + ((maxfontsize - minfontsize) * ratio)
let style = `font-size: ${parseFloat(size.toFixed(2))}${unit};`

// 最后需要修改以下代码
source.forEach(tag => {
const color = 'rgb(' + Math.floor(Math.random() * 201) + ', ' + Math.floor(Math.random() * 201) + ', ' + Math.floor(Math.random() * 201) + ')' // 0,0,0 -> 200,200,200
let style = ` color: ${color}`
result += `<a href="${env.url_for(tag.path)}" style="${style}">${tag.name}</a>`
})

如果你还想再给标签从大到小排个序的话,那么就是我正在使用的这个了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
hexo.extend.helper.register('cloudTags', function(options = {}) {
const env = this
let source = options.source
const limit = options.limit
// 从小到大排序然后再翻转,即从大到小排序
source = source.sort('length').reverse()
let result = ''
if (limit > 0) source = source.limit(limit)

source.forEach(tag => {
const color = 'rgb(' + Math.floor(Math.random() * 201) + ', ' + Math.floor(Math.random() * 201) + ', ' + Math.floor(Math.random() * 201) + ')' // 0,0,0 -> 200,200,200
result += `<a href="${env.url_for(tag.path)}" style="color: ${color}">${tag.name} (${tag.length})</a>`
})
return result
})

修改样式

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

/* 标签 */

#aside-content .card-tag-cloud a {
border: 1px solid;
line-height: 1.5;
border-radius: 6px;
margin: 3px;
padding: 0 5px;
}

.tag-cloud-list a {
border: 1px solid;
line-height: 1.5;
border-radius: 6px;
padding: 5px 15px;
font-size: 1.2rem;
margin: 5px;
}

魔改友链页面

魔改友链页面

原文:Hexo博客友链样式修改 | Leonus

友链创建教程:Butterfly 安裝文檔(二) 主題頁面 | Butterfly

修改源码

HexoRoot/source新建_data文件夹,新建link.yml,格式类似以下代码:

1
2
3
4
5
6
7
- class_name: 友情链接
class_desc: 博主
link_list:
- name: 枫叶
link: https://blog.aqcoder.cn
avatar: https://blog.aqcoder.cn/img/avatar.png
descr: 分享知识,认识世界

修改butterfly\layout\includes\page\flink.pug

1
2
3
4
5
6
if site.data.link
- let result = ""
each i in site.data.link
- - let className = i.class_name ? markdown(`## ${i.class_name}`) : ""
+ - let className = i.class_name ? markdown(`## ${i.class_name} (${i.link_list.length})`) : ""
- let classDesc = i.class_desc ? `<div class="flink-desc">${i.class_desc}</div>` : ""

修改butterfly\layout\includes\page\flink.pug 的第54行,使用flink_url的修改第24行:

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
# 使用flink_url,修改的代码第24行
listResult += `
<div class="flink-list-item">
- <a href="${lists[j].link}" title="${lists[j].name}" target="_blank">
+ <a href="${lists[j].link}" title="${lists[j].name}" target="_blank">
<div class="flink-item-icon">
<img class="no-lightbox" src="${lists[j].avatar}" onerror='this.onerror=null;this.src="!{url_for(theme.error_img.flink)}"' alt="${lists[j].name}" />
</div>
<div class="flink-item-name">${lists[j].name}</div>
<div class="flink-item-desc" title="${lists[j].descr}">${lists[j].descr}</div>
</a>
</div>`


# 使用_data,修改的代码第54行
listResult += `
<div class="flink-list-item">
- <a href="${j.link}" title="${j.name}" target="_blank">
+ <a href="${j.link}" title="${j.name}" target="_blank">
<div class="flink-item-icon">
<img class="no-lightbox" src="${j.avatar}" onerror='this.onerror=null;this.src="${url_for(theme.error_img.flink)}"' alt="${j.name}" />
</div>
<div class="flink-item-name">${j.name}</div>
<div class="flink-item-desc" title="${j.descr}">${j.descr}</div>
</a>
</div>`

添加自定义css

HexoRoot/source新建css文件夹,新建links.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
/* 头像微调 */
.flink-item-icon {
margin-right: 0 !important;
transition: .5s !important;
}

.flink-item-name,
.flink-item-desc {
padding-left: 10px !important;
}

/* 去掉原来自带的before */
#article-container .flink .flink-list>.flink-list-item::before {
content: none;
}

/* 鼠标经过改变背景 */
#article-container .flink .flink-list>.flink-list-item:hover {
background-color: #61bcf2cc;
box-shadow: 0 0 20px rgba(0, 0, 0, .3);
}

/* 鼠标经过改变文字颜色 */
#article-container .flink .flink-list>.flink-list-item:hover a {
color: white !important;
}

/* 鼠标经过头像滚动 */
#article-container .flink .flink-list>.flink-list-item:hover .flink-item-icon {
width: 60px;
margin-left: -70px;
-webkit-transform: rotate(-180deg);
-moz-transform: rotate(-180deg);
-o-transform: rotate(-180deg);
-ms-transform: rotate(-180deg);
transform: rotate(-180deg);
}

_config.butterfly.yml引入css

1
2
3
4
inject:
head:
+ - <link rel="stylesheet" href="/css/style.css?1">
bottom:

添加侧边栏访问统计

image-20221027225344672

原文:51la统计美化 | Leonus

重点

md文件中添加以下代码:

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
## 博客统计

### 访客统计
<div id="pvisitor">
<div class="content"></div>
</div>

### 访客信息
<div id="ivisitor">
<div class="content"></div>
</div>

<link rel="stylesheet" href="/css/visitor.css">

<script>
fetch('https://v6-widget.51.la/v6/K3C3rxPX9ZnLFSM9/quote.js').then(res => res.text()).then((data) => {
let title = ['最近活跃访客', '今日访问人数', '今日访问量', '昨日人数', '昨日访问量', '本月访问量', '总访问量']
let num = data.match(/(?<=<\/span><span>).*?(?=<\/span><\/p>)/g)
let s = document.querySelectorAll('#pvisitor .content')[0]
for (let i = 0; i < num.length; i++) {
if (i == 3 || i == 4) continue;
s.innerHTML += '<div><span>' + title[i] + '</span><span class="num">' + num[i] + '</span></div>'
}
});
fetch('https://api.vvhan.com/api/visitor.info').then(res => res.json()).then((data) => { //获取访客信息
let c = document.querySelectorAll('#ivisitor .content')[0]
var system = data['system']
var addr = data['location']==='---'?'未知':data['location']
var ipaddr = data['ip']
var weather = data['tq']+"&nbsp"+data['low'].replace("最低 ","")+"~"+data['high'].replace("最高 ","")
var tip = data['tip']
system = system==="未知操作系统"?"移动端":system
addr = addr===null?"未知":addr
ipaddr = ipaddr===null?"未知":ipaddr
weather = weather===null?"未知":weather
tip = tip===null?"未知":tip
c.innerHTML = `<div><span>系统</span><span class="num">${system}</span></div>
<div><span>地址</span><span class="num">${addr}</span></div>
<div><span>IP地址</span><span class="num">${ipaddr}</span></div>
<div><span>天气</span><span class="num">${weather}</span></div>
<div><span>温馨提示</span><span class="num">
<div style="width:100% !important"><span style="font-size:1.5rem;font-weight:bold;display:block;">${tip}</span></div>
</span></div>
`
});
</script>

这里我修改了部分代码以适配我的博客

添加侧边栏统计

除此之外,根据大佬记录的代码,我增加了侧边栏统计的样式

侧边栏统计

自定义侧边栏可参考官方文档:https://butterfly.js.org/posts/ea33ab97/

步骤如下:

1、新建博客根目录/source/_data/widget.yml,添加代码:

1
2
3
4
5
6
7
bottom:
- class_name:
id_name:
name: 访问统计
icon: iconfont icon-tongji
order: 1
html: <link rel="stylesheet" href="/css/visitor.css"><div id="visitor"><div class="content"></div></div><script src="/js/visitor.js"></script>

2、新建博客根目录/source/js/visitor.js,添加代码:

1
2
3
4
5
6
7
8
9
10
11
12
// 侧边栏访问统计
fetch('https://v6-widget.51.la/v6/K3C3rxPX9ZnLFSM9/quote.js').then(res => res.text()).then((data) => {
let title = ['最近活跃访客', '今日访问人数', '今日访问量', '昨日人数', '昨日访问量', '本月访问量', '总访问量']
let num = data.match(/(?<=<\/span><span>).*?(?=<\/span><\/p>)/g)
let s = document.querySelectorAll('#visitor .content')[0]
if (s !== undefined) {
for (let i = 0; i < num.length; i++) {
if (i == 3 || i == 4) continue;
s.innerHTML += '<div><p><span id=name>' + title[i] + '</span><span class="num">' + num[i] + '</span></p></div>'
}
}
});

K3C3rxPX9ZnLFSM9改为自己的,获取方式可参照:Butterfly 博客搭建(进阶教程)

3、新建博客根目录/source/css/visitor.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
/* 关于页面访问统计、访客信息样式 */
#pvisitor,
#ivisitor {
font-size: 18px;
padding: 20px;
border-radius: 12px;
width: 100%;
color: var(--font-color);
background-color: var(--card-bg);
}

div#pvisitor .content,
div#ivisitor .content {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}

div#pvisitor a,
div#ivisitor a {
text-decoration: none;
}

#pvisitor .content div,
#ivisitor .content div {
display: inline-block;
}

#pvisitor div span,
#ivisitor div span {
font-size: 14px;
line-height: 1.3;
display: block;
}

#pvisitor div .num,
#ivisitor div .num {
letter-spacing: 1px;
font-weight: bold;
font-size: 1.6rem;
margin-bottom: .8rem;
}

/* 侧边栏访问统计样式 */
#visitor {
box-sizing: border-box !important;
margin: 0px !important;
font-size: 18px !important;
line-height: 1.7 !important;
color: rgb(51, 51, 51) !important;
background-color: rgb(255, 255, 255) !important;
padding: 16px 0px !important;
border: 1px solid rgb(255, 255, 255) !important;
height: auto !important;
}

#visitor div p {
margin: 0px !important;
text-align: left !important;
}

#visitor div #name {
color: rgb(137, 137, 137) !important;
display: inline-block !important;
}

#visitor div .num {
color: rgb(51, 51, 51) !important;
font-weight: bold !important;
float: right !important;
}

添加文章统计图

原文:Hexo 博客文章统计图 | Eurkon

重点

[Blogroot]\themes\butterfly\scripts\helpers\ 目录下新建 charts.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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
const cheerio = require('cheerio')
const moment = require('moment')

hexo.extend.filter.register('after_render:html', function (locals) {
const $ = cheerio.load(locals)
const post = $('#posts-chart')
const tag = $('#tags-chart')
const category = $('#categories-chart')
const htmlEncode = false

if (post.length > 0 || tag.length > 0 || category.length > 0) {
if (post.length > 0 && $('#postsChart').length === 0) {
if (post.attr('data-encode') === 'true') htmlEncode = true
post.after(postsChart(post.attr('data-start')))
}
if (tag.length > 0 && $('#tagsChart').length === 0) {
if (tag.attr('data-encode') === 'true') htmlEncode = true
tag.after(tagsChart(tag.attr('data-length')))
}
if (category.length > 0 && $('#categoriesChart').length === 0) {
if (category.attr('data-encode') === 'true') htmlEncode = true
category.after(categoriesChart(category.attr('data-parent')))
}

if (htmlEncode) {
return $.root().html().replace(/&amp;#/g, '&#')
} else {
return $.root().html()
}
} else {
return locals
}
}, 15)

function postsChart (startMonth) {
const startDate = moment(startMonth || '2022-07')
const endDate = moment()

const monthMap = new Map()
const dayTime = 3600 * 24 * 1000
for (let time = startDate; time <= endDate; time += dayTime) {
const month = moment(time).format('YYYY-MM')
if (!monthMap.has(month)) {
monthMap.set(month, 0)
}
}
hexo.locals.get('posts').forEach(function (post) {
const month = post.date.format('YYYY-MM')
if (monthMap.has(month)) {
monthMap.set(month, monthMap.get(month) + 1)
}
})
const monthArr = JSON.stringify([...monthMap.keys()])
const monthValueArr = JSON.stringify([...monthMap.values()])

return `
<script id="postsChart">
var color = document.documentElement.getAttribute('data-theme') === 'light' ? '#4c4948' : 'rgba(255,255,255,0.7)'
var postsChart = echarts.init(document.getElementById('posts-chart'), 'light');
var postsOption = {
title: {
text: '文章发布统计图',
x: 'center',
textStyle: {
color: color
}
},
tooltip: {
trigger: 'axis'
},
xAxis: {
name: '日期',
type: 'category',
boundaryGap: false,
nameTextStyle: {
color: color
},
axisTick: {
show: false
},
axisLabel: {
show: true,
color: color
},
axisLine: {
show: true,
lineStyle: {
color: color
}
},
data: ${monthArr}
},
yAxis: {
name: '文章篇数',
type: 'value',
nameTextStyle: {
color: color
},
splitLine: {
show: false
},
axisTick: {
show: false
},
axisLabel: {
show: true,
color: color
},
axisLine: {
show: true,
lineStyle: {
color: color
}
}
},
series: [{
name: '文章篇数',
type: 'line',
smooth: true,
lineStyle: {
width: 0
},
showSymbol: false,
itemStyle: {
opacity: 1,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgba(128, 255, 165)'
},
{
offset: 1,
color: 'rgba(1, 191, 236)'
}])
},
areaStyle: {
opacity: 1,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgba(128, 255, 165)'
}, {
offset: 1,
color: 'rgba(1, 191, 236)'
}])
},
data: ${monthValueArr},
markLine: {
data: [{
name: '平均值',
type: 'average',
label: {
color: color
}
}]
}
}]
};
postsChart.setOption(postsOption);
window.addEventListener('resize', () => {
postsChart.resize();
});
postsChart.on('click', 'series', (event) => {
if (event.componentType === 'series') window.location.href = '/archives/' + event.name.replace('-', '/');
});
</script>`
}

function tagsChart (len) {
const tagArr = []
hexo.locals.get('tags').map(function (tag) {
tagArr.push({ name: tag.name, value: tag.length, path: tag.path })
})
tagArr.sort((a, b) => { return b.value - a.value })

const dataLength = Math.min(tagArr.length, len) || tagArr.length
const tagNameArr = []
for (let i = 0; i < dataLength; i++) {
tagNameArr.push(tagArr[i].name)
}
const tagNameArrJson = JSON.stringify(tagNameArr)
const tagArrJson = JSON.stringify(tagArr)

return `
<script id="tagsChart">
var color = document.documentElement.getAttribute('data-theme') === 'light' ? '#4c4948' : 'rgba(255,255,255,0.7)'
var tagsChart = echarts.init(document.getElementById('tags-chart'), 'light');
var tagsOption = {
title: {
text: 'Top ${dataLength} 标签统计图',
x: 'center',
textStyle: {
color: color
}
},
tooltip: {},
xAxis: {
name: '标签',
type: 'category',
nameTextStyle: {
color: color
},
axisTick: {
show: false
},
grid: {
lineHeight: 32
},
axisLabel: {
show: true,
color: color,
interval: 0,
formatter: function(value){
var res = "";
var max_strlen = 5;
var strlen = 0;
for (var i = 0; i < value.length; i++) {
if (value.charCodeAt(i) > 255)
strlen++;
else
strlen+=0.8;
if (strlen>max_strlen){
res+="\\n"
strlen=0;
}
res+=value.charAt(i);
}
return res;
},
// rotate: 40,
},
axisLine: {
show: true,
lineStyle: {
color: color
}
},
data: ${tagNameArrJson}
},
yAxis: {
name: '文章篇数',
type: 'value',
splitLine: {
show: false
},
nameTextStyle: {
color: color
},
axisTick: {
show: false
},
axisLabel: {
show: true,
color: color
},
axisLine: {
show: true,
lineStyle: {
color: color
}
}
},
series: [{
name: '文章篇数',
type: 'bar',
data: ${tagArrJson},
itemStyle: {
borderRadius: [5, 5, 0, 0],
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgba(128, 255, 165)'
},
{
offset: 1,
color: 'rgba(1, 191, 236)'
}])
},
emphasis: {
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgba(128, 255, 195)'
},
{
offset: 1,
color: 'rgba(1, 211, 255)'
}])
}
},
markLine: {
data: [{
name: '平均值',
type: 'average',
label: {
color: color
}
}]
}
}]
};
tagsChart.setOption(tagsOption);
window.addEventListener('resize', () => {
tagsChart.resize();
});
tagsChart.on('click', 'series', (event) => {
if(event.data.path) window.location.href = '/' + event.data.path;
});
</script>`
}

function categoriesChart (dataParent) {
const categoryArr = []
let categoryParentFlag = false
hexo.locals.get('categories').map(function (category) {
if (category.parent) categoryParentFlag = true
categoryArr.push({
name: category.name,
value: category.length,
path: category.path,
id: category._id,
parentId: category.parent || '0'
})
})
categoryParentFlag = categoryParentFlag && dataParent === 'true'
categoryArr.sort((a, b) => { return b.value - a.value })
function translateListToTree (data, parent) {
let tree = []
let temp
data.forEach((item, index) => {
if (data[index].parentId == parent) {
let obj = data[index];
temp = translateListToTree(data, data[index].id);
if (temp.length > 0) {
obj.children = temp
}
if (tree.indexOf())
tree.push(obj)
}
})
return tree
}
const categoryNameJson = JSON.stringify(categoryArr.map(function (category) { return category.name }))
const categoryArrJson = JSON.stringify(categoryArr)
const categoryArrParentJson = JSON.stringify(translateListToTree(categoryArr, '0'))

return `
<script id="categoriesChart">
var color = document.documentElement.getAttribute('data-theme') === 'light' ? '#4c4948' : 'rgba(255,255,255,0.7)'
var categoriesChart = echarts.init(document.getElementById('categories-chart'), 'light');
var categoryParentFlag = ${categoryParentFlag}
var categoriesOption = {
title: {
text: '文章分类统计图',
x: 'center',
textStyle: {
color: color
}
},
legend: {
top: 'bottom',
data: ${categoryNameJson},
textStyle: {
color: color
}
},
tooltip: {
trigger: 'item'
},
series: []
};
categoriesOption.series.push(
categoryParentFlag ?
{
nodeClick :false,
name: '文章篇数',
type: 'sunburst',
radius: ['15%', '90%'],
center: ['50%', '55%'],
sort: 'desc',
data: ${categoryArrParentJson},
itemStyle: {
borderColor: '#fff',
borderWidth: 2,
emphasis: {
focus: 'ancestor',
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(255, 255, 255, 0.5)'
}
}
}
:
{
name: '文章篇数',
type: 'pie',
radius: [30, 80],
roseType: 'area',
label: {
color: color,
formatter: '{b} : {c} ({d}%)'
},
data: ${categoryArrJson},
itemStyle: {
emphasis: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(255, 255, 255, 0.5)'
}
}
}
)
categoriesChart.setOption(categoriesOption);
window.addEventListener('resize', () => {
categoriesChart.resize();
});
categoriesChart.on('click', 'series', (event) => {
if(event.data.path) window.location.href = '/' + event.data.path;
});
</script>`
}

.md文件使用:

1
2
3
4
5
6
7
<script src="https://npm.elemecdn.com/echarts@4.9.0/dist/echarts.min.js"></script>
<!-- 文章发布时间统计图 -->
<div id="posts-chart" data-start="2022-07" style="border-radius: 8px; height: 300px; padding: 10px;margin-top:30px"></div>
<!-- 文章标签统计图 -->
<div id="tags-chart" data-length="10" style="border-radius: 8px; height: 300px; padding: 10px;"></div>
<!-- 文章分类统计图 -->
<div id="categories-chart" data-parent="true" style="border-radius: 8px; height: 300px; padding: 10px;margin-top:30px"></div>

为了适配我的长标签,我在在标签统计图中添加了以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
formatter: function(value){
var res = "";
var max_strlen = 5;
var strlen = 0;
for (var i = 0; i < value.length; i++) {
if (value.charCodeAt(i) > 255)
strlen++;
else
strlen+=0.8;
if (strlen>max_strlen){
res+="\\n"
strlen=0;
}
res+=value.charAt(i);
}
return res;
},

效果如图:

文章统计图

魔改Twikoo样式

魔改信息栏

点击评论系统的输入框会出现提示:

友好提示

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
/* Twikoo评论系统样式 */
/* 设置文字内容 :nth-child(1)的作用是选择第几个 */
.el-input.el-input--small.el-input-group.el-input-group--prepend:nth-child(1):before {
content: '输入QQ号会自动获取昵称和头像🐧';
}

.el-input.el-input--small.el-input-group.el-input-group--prepend:nth-child(2):before {
content: '收到回复将会发送到您的邮箱📧';
}

.el-input.el-input--small.el-input-group.el-input-group--prepend:nth-child(3):before {
content: '可以通过昵称访问您的网站🔗';
}

/* 当用户点击输入框时显示 */
.el-input.el-input--small.el-input-group.el-input-group--prepend:focus-within::before,
.el-input.el-input--small.el-input-group.el-input-group--prepend:focus-within::after {
display: block;
}

/* 主内容区 */
.el-input.el-input--small.el-input-group.el-input-group--prepend::before {
/* 先隐藏起来 */
display: none;
/* 绝对定位 */
position: absolute;
/* 向上移动60像素 */
top: -60px;
/* 文字强制不换行,防止left:50%导致的文字换行 */
white-space: nowrap;
/* 圆角 */
border-radius: 10px;
/* 距离左边50% */
left: 50%;
/* 然后再向左边挪动自身的一半,即可实现居中 */
transform: translate(-50%);
/* 填充 */
padding: 14px 18px;
background: #444;
color: #fff;
}

/* 小角标 */
.el-input.el-input--small.el-input-group.el-input-group--prepend::after {
display: none;
content: '';
position: absolute;
/* 内容大小(宽高)为0且边框大小不为0的情况下,每一条边(4个边)都是一个三角形,组成一个正方形。
我们先将所有边框透明,再给其中的一条边添加颜色就可以实现小三角图标 */
border: 12px solid transparent;
border-top-color: #444;
left: 50%;
transform: translate(-50%, -48px);
}

魔改评论区

原文

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
123
124
125
126
127
128
129
/* 声名部分变量 */
:root {
--cxl2020mc-radius: 7px;
--cxl2020mc-card-border-width: 1px;
}

/* 浅色模式颜色 */
[data-theme=light] {
--cxl2020mc-border-color: #e3e8f7;
--cxl2020mc-card-bg: #fff;
--cxl2020mc-card-border: #e3e8f7;
--style-border-always: 1px solid var(--cxl2020mc-card-border);
--cxl2020mc-blue: #425AEF;
}

/* 深色模式颜色 */
[data-theme=dark] {
--cxl2020mc-border-color: #42444a;
--cxl2020mc-card-bg: #1d1b26;
--cxl2020mc-card-border: #42444a;
--style-border-always: 1px solid var(--cxl2020mc-card-border);
--cxl2020mc-blue: #0084FF;
}

/* 评论区评论大框 */
.twikoo .tk-comments-container>.tk-comment {
/* 内边距 */
padding: 1rem;
/* 圆角 */
border-radius: var(--cxl2020mc-radius);
/* 背景颜色 */
background: var(--cxl2020mc-card-bg);
/* 变动动画时长 */
transition: .3s;
}

/* 浅色模式评论区评论大框 */
[data-theme=light] .twikoo .tk-comments-container>.tk-comment {
/* 阴影 */
box-shadow: var(--card-box-shadow);
}

/* 浅色模式评论区评论大框阴影悬浮加深 */
[data-theme=light] .twikoo .tk-comments-container>.tk-comment:hover {
/* 阴影(浅色模式突出层次感) */
box-shadow: var(--card-hover-box-shadow);
}

/* 黑暗模式评论区评论大框 */
[data-theme=dark] .twikoo .tk-comments-container>.tk-comment {
/* 边框样式 */
border-style: solid;
/* 边框宽度 */
border-width: var(--cxl2020mc-card-border-width);
/* 边框颜色 */
border-color: var(--cxl2020mc-card-border);
}

/* 设备信息 */
.twikoo .tk-extra {
/* 圆角 */
border-radius: var(--cxl2020mc-radius);
/* 背景颜色 */
background: var(--cxl2020mc-card-bg);
/* 内边距 */
padding: 0.4rem;
/* 底边距 */
margin-bottom: 1rem;
/* 变动动画时长 */
transition: .3s;
}

/* 浅色模式设备信息 */
[data-theme=light] .twikoo .tk-extra {
/* 阴影 */
box-shadow: var(--card-box-shadow);
}

/* 浅色模式设备信息阴影悬浮加深 */
[data-theme=light] .twikoo .tk-extra:hover {
/* 阴影 */
box-shadow: var(--card-hover-box-shadow);
}

/* 黑暗模式设备信息 */
[data-theme=dark] .twikoo .tk-extra {
/* 边框样式 */
border-style: solid;
/* 边框宽度 */
border-width: var(--cxl2020mc-card-border-width);
/* 边框颜色 */
border-color: var(--cxl2020mc-card-border);
}

/* 加载更多按钮 */
.twikoo .tk-expand {
/* 圆角 */
border-radius: var(--cxl2020mc-radius);
}

/* 浅色模式加载更多按钮 */
[data-theme=light] .twikoo .tk-expand {
/* 阴影 */
box-shadow: var(--card-box-shadow);
}

/* 浅色模式加载更多按钮(鼠标悬浮时) */
[data-theme=light] .twikoo .tk-expand:hover {
/* 阴影 */
box-shadow: var(--card-hover-box-shadow);
/* 背景颜色 */
background-color: var(--btn-bg);
}

/* 黑暗模式加载更多按钮(鼠标悬浮时) */
[data-theme=dark] .twikoo .tk-expand:hover {
/* 背景颜色 */
background-color: var(--cxl2020mc-blue);
}

/* 黑暗模式加载更多按钮 */
[data-theme=dark] .twikoo .tk-expand {
/* 边框样式 */
border-style: solid;
/* 边框宽度 */
border-width: var(--cxl2020mc-card-border-width);
/* 边框颜色 */
border-color: var(--cxl2020mc-card-border);
}

魔改页脚

魔改页脚

原文:Butterfly 主题页脚美化 | Jayhrn - 分享科技与热爱生活

修改 themes/butterfly/layout/includes/footer.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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#footer_deal
a.deal_link(href="mailto:1982989137@qq.com" title="mail")
i.iconfont.icon-youxiang1
a.deal_link(href="https://res.abeim.cn/api/qq/?qq=1982989137" title="qq" target="_blank")
i.iconfont.icon-qq1
a.deal_link(href="https://weibo.com/flow2000" title="微博" target="_blank")
i.iconfont.icon-weibo
a.deal_link(href="https://github.com/flow2000" title="github" target="_blank")
i.iconfont.icon-github
img.footer_mini_logo.entered.loading(style="border-radius:50%" src='/img/avatar.png' onclick="btf.scrollToDest(0,500)" title="返回顶部")
a.deal_link(href="/" title="主页" target="_blank")
i.iconfont.icon-zhuye
a.deal_link(href="https://travellings.cn/" title="开往-随机跳转另一个加入开往的网页" target="_blank")
i.iconfont.icon-huoche
a.deal_link(href="/comment/" title="留言" target="_blank")
i.iconfont.icon-liuyan
a.deal_link(href="/atom.xml" title="rss" target="_blank")
i.iconfont.icon-rss
#Jay-footer
.footer-group
h3.footer-title 直达
.footer-links
a.footer-item(href="/" target="_blank") 我的主页
a.footer-item(href="javascript:toRandomPost();") 随机文章
a.footer-item(href="https://bimg.cc" target="_blank") 必应壁纸
.footer-group
h3.footer-title 分类
.footer-links
a.footer-item(href="/categories/优秀文章/") 优秀文章
a.footer-item(href="/categories/博客搭建/") 博客搭建
a.footer-item(href="/categories/学习笔记/") 学习笔记
a.footer-item(href="/categories/实用教程/") 实用教程
a.footer-item(href="/categories/总结/") 总结
.footer-group
h3.footer-title 友链
.footer-links#friend-links-in-footer
a.footer-item(href="https://blog.zhheo.com/" target="_blank") 张洪Heo
a.footer-item(href="https://zfe.one/" target="_blank") 小冰博客
a.footer-item(href="https://blog.leonus.cn/" target="_blank") Leonus
a.footer-item(href="https://zhangshier.vip/" target="_blank") 张时贰
a.footer-item(href="/links/" target="_blank") 查看更多
.footer-group
h3.footer-title 关于
.footer-links
a.footer-item(href="/about/") 关于我
a.footer-item(href="/about/#博客统计") 博客统计
a.footer-item(href="/archives/") 文章归档
a.footer-item(href="/history/") 建站记录
#footer-banner
.footer-banner-links
.footer-banner-left
.footer-banner-left
#footer-banner-tips

.footer-banner-right
a.footer-banner-link(href="https://beian.miit.gov.cn/" title="备案") 桂ICP备2021004373号-4
a.footer-banner-link(href="https://hexo.io/zh-cn/" title="Hexo") 框架
a.footer-banner-link |
a.footer-banner-link(href="https://github.com/jerryc127/hexo-theme-butterfly" title="theme") 主题
a.footer-banner-link |
a.footer-banner-link(href="/atom.xml" title="RSS") 订阅
a.footer-banner-link |
a.footer-banner-link(href="/about/" title="about") 关于
a.footer-banner-link

图标需要自己修改,引入第三方图标库还请查阅官方文档:Butterfly 安裝文檔(六) 進階教程 | Butterfly