前面我们利用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
安装pug 和 stylus 渲染器。 npm install hexo-renderer-pug hexo-renderer-stylus --save
修改项目根目录下的_config.yml文件(称为站点配置文件),开启主题。 !注意:
为了減少升级主题带来的不便,我们可以把主题文件夹中(即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}" # 如果没有查到内容相关内容显示
效果:给网站增加一个搜索栏
图片懒加载插件 npm install hexo-lazyload-image --save
在 _config.yml 中添加以下配置(注意是系统设置文件不是主题设置文件):
lazyload: enable: true loadingImg: /img/loading.gif
效果:当图片资源加载时用设置的动态加载图片覆盖图片异常显示
字数统计插件 npm install hexo-wordcount --save or yarn add hexo-wordcount
在 _config.butterfly.yml 中修改以下配置:
wordcount: enable: true post_wordcount: true min2read: true total_wordcount: true
效果如下:
个性化设置 修改顶部菜单 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 留言板: /comment/ || fa fa-paper-plane 关于笔者: /about/ || fas fa-heart
必须是 /xxx/,后面||分开,然后写图标名,如果不想显示图标,图标名可不写
注意这里只是创建了导航菜单的·标签,我们还要新建对应的标签页:
文件位置:
打开对应文件夹下的index.md,加上对应的type:
title: tags date: 2025-09-03 13:09:06 type: "tags"
最终效果如下:
修改个人信息 修改配置文件 _config.yml
title: Ersami个人博客 subtitle: '' description: 记录生活 keywords: author: Ersami language: zh-CN timezone: Asia/Shanghai
修改侧边栏 修改配置文件 _config.butterfly.yml
aside: enable: true hide: false button: true mobile: true position: left
添加个人链接:
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
fa-github是框架自带的图标库,Butterfly支持font-awesome v6 图标,当然你也可以根据自身需求进行定制。
效果如下:
图片设置 图片放在在/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这样的效果可以让你的背景图保持简洁(”一图流“)
background: /img/bg.png default_top_img: rgba(0, 0 , 0 , 0 ) 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 highlight_copy: true highlight_lang: false highlight_shrink: false highlight_height_limit: false code_word_wrap: true
同时将站点配置文件_config.yml的highlight设置为false:
highlight: enable: false line_number: false auto_detect: false
副标题循环打字效果 打开配置文件 _config.butterfly.yml:
subtitle: enable: true effect: true loop: true source: false sub: - 你在抱怨什么呢 - 为明天到来的事,说人生像是没有意义 - 没有选择会是唯一的路 - 这不是你自己的问题,人终归要好好去生活
效果如下:
鼠标样式魔改 新建文件[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" ))); 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 (); })();
其中比较重要的参数就是鼠标的尺寸和颜色,已经在上面的代码中标出,可以自行调节。
在[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: enable: true scriptFrom: local pluginRootPath: live2dw/ pluginJsPath: lib/ pluginModelPath: assets/ tagMode: false debug: false model: use: live2d-widget-model-wanko 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
完成后保存修改,在Hexo根目录下运行指令
之所以必须要使用hexo clean是因为我们需要清空缓存重新生成静态页面,不然看板娘没被加入生成的静态页面里,是不会出现的。
效果如下:
卸载看板娘
npm uninstall hexo-helper-live2d npm uninstall live2d-widget-model-modelname
卸载后为了保证配置项不出错,记得把[Blogroot]\_config.yml里的配置项给注释或者删除掉。
文章置顶滚动栏 安装插件,在博客根目录[BlogRoot]下打开终端,运行以下指令:
npm install hexo-butterfly-swiper --save
在站点配置文件_config.yml或者主题配置文件_config.butterfly.yml中添加:
swiper: enable: true priority: 5 enable_page: all timemode: date layout: type: id name: recent-posts index: 0 default_descr: 再怎么看我也不知道怎么描述它的啦! swiper_css: https://npm.elemecdn.com/hexo-butterfly-swiper/lib/swiper.min.css swiper_js: https://npm.elemecdn.com/hexo-butterfly-swiper/lib/swiper.min.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
文章分享功能 打开[Blogroot]\_config.yml
addThis、sharejs、addtoany三个选一个开启
addThis官网:https://www.addthis.com/
addThis: enable: false pubid: sharejs: enable: true sites: facebook,twitter,wechat,weibo,qq addtoany: enable: false item: facebook,twitter,wechat,sina_weibo,facebook_messenger,email,copy_link
我这里使用的时默认的sharejs
share: use: sharejs sharejs: sites: wechat,weibo,qq addtoany: item: facebook,twitter,wechat,sina_weibo,facebook_messenger,email,copy_link
部署 在本地完成修改后,在根目录进入cmd,依次输入hexo g、hexo deploy就可以重新部署了。