前面我们利用Hexo搭建了一个网站的框架雏形,接下来我们结合Butterfly来对我们的网站进行美化。

什么是Butterfly?

Butterfly:轻量级、高效的Web开发框架

是一个由Python构建的微型Web框架,专注于提供简单、优雅且高效的Web应用解决方案。它以其简洁的API设计和灵活的可扩展性赢得了开发者们的青睐。

Butterfly的核心理念是“少即是多”,即通过最小化代码量实现最大化的功能。它借鉴了其他知名框架如Flask和Django的优点,并在它们的基础上进行了创新。Butterfly的设计目标是让开发者能够快速地搭建和部署Web应用程序,同时保持代码的高度可读性和维护性。

安装Butterfly主题

hexo项目根目录下下载主题。

git clone -b master https://github.com/jerryc127/hexo-theme-butterfly.git themes/butterfly

安装pugstylus 渲染器。

npm install hexo-renderer-pug hexo-renderer-stylus --save

修改项目根目录下的_config.yml文件(称为站点配置文件),开启主题。

# Extensions
## Plugins: https://hexo.io/plugins/
## Themes: https://hexo.io/themes/
theme: butterfly

!注意:

为了減少升级主题带来的不便,我们可以把主题文件夹中(即themes文件夹)的 _config.yml 重命名为 _config.butterfly.yml,复制到 Hexo 根目录下与_config.yml同级。

Hexo会自动合并主题中的_config.yml_config.butterfly.yml ,如果存在同名配置,会使用_config.butterfly.yml的配置,其优先度较高。所以像和博客网址相关联的固定资料可以设置在_config.yml中,比如博客的标题、作者信息和邮箱等等资料,而和主题样式相关的配置放在 _config.butterfly.yml 中,那么在将来你想换一个主题是很方便的。

安装插件

搜索插件

npm install hexo-generator-search --save

更改配置文件 _config.butterfly.yml:

use: local_search
. . .

# Local Search
local_search:
enable: true
labels:
input_placeholder: Search for Posts
hits_empty: "We didn't find any results for the search: ${query}" # 如果没有查到内容相关内容显示

效果:给网站增加一个搜索栏

image-20250903180333999

image-20250903180339824

图片懒加载插件

npm install hexo-lazyload-image --save

_config.yml 中添加以下配置(注意是系统设置文件不是主题设置文件):

lazyload:
enable: true
loadingImg: /img/loading.gif

image-20250903180631723

效果:当图片资源加载时用设置的动态加载图片覆盖图片异常显示

image-20250903180458900

字数统计插件

npm install hexo-wordcount --save or yarn add hexo-wordcount

_config.butterfly.yml 中修改以下配置:

wordcount:
enable: true
post_wordcount: true
min2read: true
total_wordcount: true

效果如下:

image-20250903180809582

image-20250903180812883

个性化设置

修改顶部菜单

menu:
主页: / || fas fa-home
博文 || fa fa-graduation-cap:
分类: /categories/ || fa fa-archive
标签: /tags/ || fa fa-tags
归档: /archives/ || fa fa-folder-open
生活 || fas fa-list:
分享: /shuoshuo/ || fa fa-comments-o
相册: /photos/ || fa fa-camera-retro
音乐: /music/ || fa fa-music
影视: /movies/ || fas fa-video
# 友链: /links/ || fa fa-link
留言板: /comment/ || fa fa-paper-plane
#留言板: /messageboard/ || fa fa-paper-plane
关于笔者: /about/ || fas fa-heart

必须是 /xxx/,后面||分开,然后写图标名,如果不想显示图标,图标名可不写

注意这里只是创建了导航菜单的·标签,我们还要新建对应的标签页:

hexo new page tags
......

文件位置:

image-20250903181326849

打开对应文件夹下的index.md,加上对应的type:

image-20250903181422087

title: tags
date: 2025-09-03 13:09:06
type: "tags"

最终效果如下:

image-20250903181504129

修改个人信息

修改配置文件 _config.yml

title: Ersami个人博客 	#标题
subtitle: '' #副标题
description: 记录生活 #个性签名
keywords:
author: Ersami #作者
language: zh-CN #语言
timezone: Asia/Shanghai #中国的时区

修改侧边栏

修改配置文件 _config.butterfly.yml

aside:
enable: true
hide: false
# Show the button to hide the aside in bottom right button
button: true
mobile: true
# Position: left / right
position: left

添加个人链接:

# Social media links
# Formal:
# icon: link || the description || color
social:
fab fa-github: https://github.com/megumieren || Github || '#24292e'
fab fa-bilibili: https://space.bilibili.com/2127161957 || Bilibili || '#ffc0cb'
fab fa-qq: tencent://AddContact/?fromId=45&fromSubId=1&subcmd=all&uin=2381087337&website=www.oicqzone.com || QQ

aside里的card_author更改个人信息:

card_author:
enable: true
description:
button:
enable: false
# icon: fab fa-github
# text: Follow Me
# link: https://github.com/megumieren

fa-github是框架自带的图标库,Butterfly支持font-awesome v6图标,当然你也可以根据自身需求进行定制。

效果如下:

image-20250903182627516

图片设置

图片放在在/themes/butterfly/source/img文件夹下面就行

打开配置文件 _config.butterfly.yml

网站图标

favicon: /img/favicon.png

头像

avatar:
img: /img/profile_picture.png
effect: false

背景

背景建议是将封面图index_img:不设置,直接设置background: /img/背景图2.jpg,然后将顶部图像设置为透明default_top_img: rgba(0, 0, 0, 0),将footer_img设置为transparent这样的效果可以让你的背景图保持简洁(”一图流“)

# Website Background
# Can set it to color or image url
background: /img/bg.png
default_top_img: rgba(0, 0, 0, 0)
# The background image of footer
footer_img: transparent

文章封面图

打开source/_posts/xxx.md文章:

---
title: XXXXX # 标题
tags: XXXXX # 标签
categories: XXXXX # 分类
description: XXXXX # 描述
top_img: XXXXX # 顶部背景图
cover: XXXXX # 文章封面
---

代码块样式

打开配置文件 _config.butterfly.yml:

highlight_theme: mac  #  darker / pale night / light / ocean / mac / mac light / false 代码主题
highlight_copy: true # 复制按钮
highlight_lang: false # 是否显示代码语言
highlight_shrink: false # true: 代码块默认不展开 / false: 代码块默认展开 | none: 展开并隐藏折叠按钮
highlight_height_limit: false # unit: px
code_word_wrap: true #代码自动换行,关闭滚动条

同时将站点配置文件_config.ymlhighlight设置为false:

highlight:
enable: false
line_number: false
auto_detect: false

副标题循环打字效果

打开配置文件 _config.butterfly.yml:

subtitle:
enable: true
# Typewriter Effect (开启打字效果)
effect: true
# loop (循環打字)
loop: true
# source調用第三方服務
# source: false 關閉調用
# source: 1 調用搏天api的隨機語錄(簡體)
# source: 2 調用一言網的一句話(簡體)
# source: 3 調用一句網(簡體)
# source: 4 調用今日詩詞(簡體)
# subtitle 會先顯示 source , 再顯示 sub 的內容
source: false
# 如果有英文逗号' , ',请使用转义字元 ,
# 如果有英文双引号' " ',请使用转义字元 "
# 开头不允許转义字元,如需要,请把整個句子用双引号包住
# 如果关闭打字效果,subtitle只会现示sub的第一行文字
sub:
- 你在抱怨什么呢
- 为明天到来的事,说人生像是没有意义
- 没有选择会是唯一的路
- 这不是你自己的问题,人终归要好好去生活

效果如下:

image-20250903183314262

鼠标样式魔改

新建文件[BlogRoot]\source\js\cursor.js(默认是没有的),在里面写上如下代码:

var CURSOR;

Math.lerp = (a, b, n) => (1 - n) * a + n * b;

const getStyle = (el, attr) => {
try {
return window.getComputedStyle
? window.getComputedStyle(el)[attr]
: el.currentStyle[attr];
} catch (e) {}
return "";
};

class Cursor {
constructor() {
this.pos = {curr: null, prev: null};
this.pt = [];
this.create();
this.init();
this.render();
}

move(left, top) {
this.cursor.style["left"] = `${left}px`;
this.cursor.style["top"] = `${top}px`;
}

create() {
if (!this.cursor) {
this.cursor = document.createElement("div");
this.cursor.id = "cursor";
this.cursor.classList.add("hidden");
document.body.append(this.cursor);
}

var el = document.getElementsByTagName('*');
for (let i = 0; i < el.length; i++)
if (getStyle(el[i], "cursor") == "pointer")
this.pt.push(el[i].outerHTML);

document.body.appendChild((this.scr = document.createElement("style")));
// 这里改变鼠标指针的颜色 由svg生成
this.scr.innerHTML = `* {cursor: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8' width='8px' height='8px'><circle cx='4' cy='4' r='4' opacity='.5'/></svg>") 4 4, auto}`;
}

refresh() {
this.scr.remove();
this.cursor.classList.remove("hover");
this.cursor.classList.remove("active");
this.pos = {curr: null, prev: null};
this.pt = [];

this.create();
this.init();
this.render();
}

init() {
document.onmouseover = e => this.pt.includes(e.target.outerHTML) && this.cursor.classList.add("hover");
document.onmouseout = e => this.pt.includes(e.target.outerHTML) && this.cursor.classList.remove("hover");
document.onmousemove = e => {(this.pos.curr == null) && this.move(e.clientX - 8, e.clientY - 8); this.pos.curr = {x: e.clientX - 8, y: e.clientY - 8}; this.cursor.classList.remove("hidden");};
document.onmouseenter = e => this.cursor.classList.remove("hidden");
document.onmouseleave = e => this.cursor.classList.add("hidden");
document.onmousedown = e => this.cursor.classList.add("active");
document.onmouseup = e => this.cursor.classList.remove("active");
}

render() {
if (this.pos.prev) {
this.pos.prev.x = Math.lerp(this.pos.prev.x, this.pos.curr.x, 0.15);
this.pos.prev.y = Math.lerp(this.pos.prev.y, this.pos.curr.y, 0.15);
this.move(this.pos.prev.x, this.pos.prev.y);
} else {
this.pos.prev = this.pos.curr;
}
requestAnimationFrame(() => this.render());
}
}

(() => {
CURSOR = new Cursor();
// 需要重新获取列表时,使用 CURSOR.refresh()
})();

其中比较重要的参数就是鼠标的尺寸和颜色,已经在上面的代码中标出,可以自行调节。

[BlogRoot]\source\css\custom.css添加如下代码:

/* 鼠标样式 */
#cursor {
position: fixed;
width: 16px;
height: 16px;
/* 这里改变跟随的底色 */
background: var(--theme-color);
border-radius: 8px;
opacity: 0.25;
z-index: 10086;
pointer-events: none;
transition: 0.2s ease-in-out;
transition-property: background, opacity, transform;
}

#cursor.hidden {
opacity: 0;
}

#cursor.hover {
opacity: 0.1;
transform: scale(2.5);
-webkit-transform: scale(2.5);
-moz-transform: scale(2.5);
-ms-transform: scale(2.5);
-o-transform: scale(2.5);
}

#cursor.active {
opacity: 0.5;
transform: scale(0.5);
-webkit-transform: scale(0.5);
-moz-transform: scale(0.5);
-ms-transform: scale(0.5);
-o-transform: scale(0.5);
}

这里比较重要的参数就是鼠标跟随的圆形颜色,可以根据自己的喜好进行更改:

#cursor {
/* 这里改变跟随的底色 */
background: rgb(57, 197, 187);
}

最后在主题配置文件 _config.butterfly.yml文件的inject配置项引入刚刚创建的 css 文件和 js文件:

inject: 
head:
- <link rel="stylesheet" href="/css/custom.css">
bottom:
- <script defer src="/js/cursor.js"></script>

Live2D看板娘

在Hexo根目录[BlogRoot]下打开终端,输入以下指令安装必要插件:

npm install --save hexo-helper-live2d

打开站点配置文件[BlogRoot]\config.yml
搜索live2d,按照如下注释内容指示进行操作。
如果没有搜到live2d的配置项,就直接把以下内容复制到最底部。

# Live2D
## https://github.com/EYHN/hexo-helper-live2d
live2d:
enable: true #开关插件版看板娘
scriptFrom: local # 默认
pluginRootPath: live2dw/ # 插件在站点上的根目录(相对路径)
pluginJsPath: lib/ # 脚本文件相对与插件根目录路径
pluginModelPath: assets/ # 模型文件相对与插件根目录路径
# scriptFrom: jsdelivr # jsdelivr CDN
# scriptFrom: unpkg # unpkg CDN
# scriptFrom: https://npm.elemecdn.com/live2d-widget@3.x/lib/L2Dwidget.min.js # 你的自定义 url
tagMode: false # 标签模式, 是否仅替换 live2d tag标签而非插入到所有页面中
debug: false # 调试, 是否在控制台输出日志
model:
use: live2d-widget-model-wanko # npm-module package name
# use: wanko # 博客根目录/live2d_models/ 下的目录名
# use: ./wives/wanko # 相对于博客根目录的路径
# use: https://npm.elemecdn.com/live2d-widget-model-wanko@1.0.5/assets/wanko.model.json # 你的自定义 url
display:
position: right #控制看板娘位置
width: 150 #控制看板娘大小
height: 300 #控制看板娘大小
mobile:
show: false # 手机中是否展示

我这里使用live2d-widget-model-wanko模型时没有效果,所以又重新安装了另一个模型。

npm install --save live2d-widget-model-koharu

然后在站点配置文件[Blogroot]\_config.yml里找到model项修改为期望的模型。

model:
use: live2d-widget-model-koharu
# 默认为live2d-widget-model-wanko

完成后保存修改,在Hexo根目录下运行指令

hexo clean
hexo g
hexo s

之所以必须要使用hexo clean是因为我们需要清空缓存重新生成静态页面,不然看板娘没被加入生成的静态页面里,是不会出现的。

效果如下:

image-20250903184052683

卸载看板娘

npm uninstall hexo-helper-live2d #卸载看板娘插件
npm uninstall live2d-widget-model-modelname #卸载看板娘模型。记得替换modelname为看板娘名称

卸载后为了保证配置项不出错,记得把[Blogroot]\_config.yml里的配置项给注释或者删除掉。

文章置顶滚动栏

安装插件,在博客根目录[BlogRoot]下打开终端,运行以下指令:

npm install hexo-butterfly-swiper --save

在站点配置文件_config.yml或者主题配置文件_config.butterfly.yml中添加:

# 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初始化方法

文章分享功能

打开[Blogroot]\_config.yml

addThissharejsaddtoany三个选一个开启

addThis官网:https://www.addthis.com/

# Share System (分享功能)
# --------------------------------------

# AddThis
# https://www.addthis.com/
addThis:
enable: false
pubid: #访问 AddThis 官网, 找到你的 pub-id

# Share.js
# https://github.com/overtrue/share.js
sharejs:
enable: true
sites: facebook,twitter,wechat,weibo,qq #想要显示的内容

# AddToAny
# https://www.addtoany.com/
addtoany:
enable: false
item: facebook,twitter,wechat,sina_weibo,facebook_messenger,email,copy_link

我这里使用的时默认的sharejs

share:
# Choose: sharejs / addtoany
# Leave it empty if you don't need share
use: sharejs

# Share.js
# https://github.com/overtrue/share.js
sharejs:
sites: wechat,weibo,qq

# AddToAny
# https://www.addtoany.com/
addtoany:
item: facebook,twitter,wechat,sina_weibo,facebook_messenger,email,copy_link

部署

在本地完成修改后,在根目录进入cmd,依次输入hexo ghexo deploy就可以重新部署了。