阅读本篇前,请先阅读前几篇文章:
基于 Hexo 从零开始搭建个人博客(一)
基于 Hexo 从零开始搭建个人博客(二)
基于 Hexo 从零开始搭建个人博客(三)
基于 Hexo 从零开始搭建个人博客(四)
基于 Hexo 从零开始搭建个人博客(五)

前言

本站基于Hexo搭建,用的 🦋 hexo-theme-butterfly 主题 v3.7.1,请注意最新的🦋 hexo-theme-butterfly 版本已经更新到 v4.3.0

如果你是 v3.7.1 之外的版本,可能有些地方会有出入,请留意。

注意:我的博客根目录路径为 【G:/hexo-blog/blog-demo】,下文所说的根目录都是此路径,将用[BlogRoot]代替。如果不清楚根目录路径,请回到教程 基于 Hexo 从零开始搭建个人博客(二),查看你执行hexo init xxx这条命令时所选择的路径,例如我选择的路径是【G:/hexo-blog】,我的博客根目录即为【G:/hexo-blog/xxx】。

修改站点配置文件_config.yml,路径为【BlogRoot/_config.yml】。

修改主题配置文件_config.butterfly.yml,路径为【BlogRoot/_config.butterfly.yml】。

更新记录

Butterfly主题美化

生成文章唯一链接

Hexo的默认文章链接格式是年,月,日,标题这种格式来生成的。如果你的标题是中文的话,那你的URL链接就会包含中文。

permalink: :year/:month/:day/:title
  1. 前往你的Hexo博客根目录,打开cmd命令窗口执行npm install hexo-abbrlink --save
    npm install hexo-abbrlink --save
  2. 修改站点配置文件_config.ymlpermalink属性。
    - permalink: :year/:month/:day/:title/
    #修改为
    permalink: post/:abbrlink.html # post为自定义前缀
    abbrlink:
    alg: crc32 #算法: crc16(default) and crc32
    rep: hex #进制: dec(default) and hex
效果预览
查看步骤

编辑BlogRoot/node_modules/hexo-theme-butterfly/layout/includes/footer.pug文件,

将以下内容

©${theme.footer.owner.since} - ${nowYear} By ${config.author}

改为

&copy;${theme.footer.owner.since} - ${nowYear + ' '} <i id="heartbeat" class="fa fas fa-heartbeat"></i> ${config.author}

将以下内容

&copy;${nowYear} By ${config.author} 

改为

&copy;${nowYear + ' '} <i id="heartbeat" class="fa fas fa-heartbeat"></i> ${config.author}

将以下内容添加到 <head></head>标签内:

<link rel="stylesheet" href="https://fastly.jsdelivr.net/gh/HCLonely/images@master/others/heartbeat.min.css">

具体放置位置,可以参考下图:

修改标题样式

效果预览
回形针
回形针
旋转风车
旋转风车
查看步骤

BlogRoot/node_modules/hexo-theme-butterfly/source/css文件下新建 css 文件,并命名为 custom.css(命名按照自己喜好去命名,只需在主题配置文件_config.butterfly.yml中引入对应的css文件即可),将以下代码复制到新建的custom.css中。

如果想自行修改标题样式的话,将content: '\f0c1';中的内容换成自己想要的即可,如要添加动画,参考animation: avatar_turn_around 1s linear infinite;

#article-container h1:before,
#article-container h2:before,
#article-container h3:before,
#article-container h4:before,
#article-container h5:before,
#article-container h6:before,
#post .post-outdate-notice:before,
.fontawesomeIcon,
.note:not(.no-icon)::before,
hr:before {
display: inline-block;
font-weight: 600;
font-style: normal;
font-variant: normal;
font-family: 'Font Awesome 5 Free';
text-rendering: auto;
-webkit-font-smoothing: antialiased
}
#article-container h1:before,
#article-container h2:before,
#article-container h3:before,
#article-container h4:before,
#article-container h5:before,
#article-container h6:before {
position: absolute;
color: #f47466;
/* 回形针 */
content: '\f0c1';
line-height: 1;
-webkit-transition: all .2s ease-out;
-moz-transition: all .2s ease-out;
-o-transition: all .2s ease-out;
-ms-transition: all .2s ease-out;
transition: all .2s ease-out;
/* 若要使用风车效果,请去掉下面的注释 */
/* content: '\f863';
animation: avatar_turn_around 1s linear infinite; */
}
#article-container h1 {
padding-left: 1.4rem
}

#article-container h1 code {
font-size: 1rem
}

#article-container h1:before {
margin-left: -1.3rem;
top: calc(50% - .5rem);
font-size: 1rem
}

#article-container h1:hover {
padding-left: 1.6rem
}

#article-container h2 {
padding-left: 1.3rem
}

#article-container h2 code {
font-size: .9rem
}

#article-container h2:before {
margin-left: -1.4rem;
top: calc(50% - .45rem);
font-size: .9rem
}

#article-container h2:hover {
padding-left: 1.5rem
}

#article-container h3 {
padding-left: 1.2rem
}

#article-container h3 code {
font-size: .8rem;
top: calc(50% - .4rem);

}

#article-container h3:before {
margin-left: -1.2rem;
top: calc(50% - .4rem);
font-size: .8rem
}

#article-container h3:hover {
padding-left: 1.4rem
}

#article-container h4 {
padding-left: 1.1rem
}

#article-container h4 code {
font-size: .7rem
}

#article-container h4:before {
margin-left: -1rem;
top: calc(50% - .35rem);
font-size: .7rem
}

#article-container h4:hover {
padding-left: 1.3rem
}

#article-container h5 {
padding-left: 1rem
}

#article-container h5 code {
font-size: .6rem
}

#article-container h5:before {
margin-left: -.8rem;
top: calc(50% - .3rem);
font-size: .6rem
}

#article-container h5:hover {
padding-left: 1.2rem
}

#article-container h6 {
padding-left: 1rem
}

#article-container h6 code {
font-size: .6rem
}

#article-container h6:before {
margin-left: -.8rem;
top: calc(50% - .3rem);
font-size: .6rem
}

#article-container h6:hover {
padding-left: 1.2rem
}

添加豆瓣插件

如果出现了豆瓣爬取数据失败问题,建议安装较低的node版本(v12.18.0)。

前往博客根目录,打开cmd命令窗口执行npm install hexo-douban --save

npm install hexo-douban --save

修改站点配置文件_config.yml,添加如下代码:

douban:
id: 228172215
builtin: false
item_per_page: 10
book:
path: books/index.html
title: 'This is my book title'
quote: 'This is my book quote'
option:
movie:
path: movies/index.html
title: 'This is my movie title'
quote: 'This is my movie quote'
option:
game:
path: games/index.html
title: 'This is my game title'
quote: 'This is my game quote'
option:
song:
path: songs/index.html
title: 'This is my song title'
quote: 'This is my song quote'
option:
timeout: 10000
  • id: 你的豆瓣ID(纯数字格式,不是自定义的域名)。获取方法可以参考 怎样获取豆瓣的数字 ID
  • builtin: 是否将 hexo douban 命令默认嵌入进 hexo g、hexo s,使其自动执行 hexo douban 命令。默认关闭。当你的豆瓣条目较多时,也建议关闭。
  • item_per_page: 每页展示的条目数,默认 10 。
  • path: 生成页面后的路径,默认生成在 //my-blog/books/index.html 等下面。如需自定义路径,则可以修改这里。
  • title: 该页面的标题。
  • quote: 写在页面开头的一段话,支持 html 语法。
  • option: 该页面额外的 Front-matter 配置,参考 Hexo 文档。无特别需要,留空即可。
  • timeout: 爬取数据的超时时间,默认是 10000ms ,如果在使用时发现报了超时的错(ETIMEOUT)可以把这个数据设置的大一点。

在主题配置文件_config.butterfly.yml中配置以下内容:

# 如果你有使用hexo-douban,可配置這個
douban:
meta: true
movies_img: https://fastly.jsdelivr.net/gh/jerryc127/butterfly_cdn@2.1.0/top_img/movie.jpg
books_img: https://fastly.jsdelivr.net/npm/blog-gallery@1.0.0/1/20200206161657.webp
# games_img:

前往博客根目录,打开cmd命令窗口执行hexo douban

hexo douban

等待命令执行完毕,出现下图所示内容即为成功。

请注意,我的butterfly主题版本不是最新的,导航菜单栏格式请按照最新的格式写。

如下图:

添加访客地图

效果预览
查看步骤

前往 clustrmaps 网站注册一个帐号。

找到Free Tools下面的Website Widget, 点击Get Map Widget

输入你的博客网址,点击Next

根据你自己的喜好选择样式Map widgetGlobe Widget(本人使用后者)。

找到如下代码,记住 src (** 的部分):

<script type="text/javascript" id="clstr_globe" src="**********************">

BlogRoot/node_modules/hexo-theme-butterfly/layout/includes/widget文件夹新建card_map.pug文件,文件内容如下:

.card-widget.card-map
.card-content
.item-headline
i.fa.fa-globe-asia(aria-hidden="true")
span= _p('aside.card_map')
script#clstr_globe(type="text/javascript" defer="defer" src="此处填入你自己的代码")

编辑 BlogRoot/node_modules/hexo-theme-butterfly/layout/includes/widget/index.pug文件,在你想要显示的位置插入以下代码(注意格式):

if theme.aside.card_map
!=partial('includes/widget/card_map', {}, {cache:true})

具体放置位置,可以参考下图:

编辑主题配置文件_config.butterfly.yml,在card_webinfo下面添加一行card_map: true

编辑BlogRoot/node_modules/hexo-theme-butterfly/languages/zh-CN.yml文件 (请根据你的网站语言选择),找到card_announcement: 公告 , 在下面添加一行card_map: 访客地图 (后面的文本可自定义),繁体字方法一样,修改BlogRoot/node_modules/hexo-theme-butterfly/languages/zh-TW.yml文件就行。

如果不想显示,直接把主题配置文件_config.butterfly.yml中的card_map: true 改为 card_map: false 即可。

添加Pixiv日榜

效果预览
查看步骤
  1. BlogRoot/node_modules/hexo-theme-butterfly/layout/includes/widget文件夹新建 card_pixiv.pug文件,文件内容如下:

    .card-widget.card-pixiv
    .card-content
    .item-headline
    i.fa.fa-image(aria-hidden="true")
    span= _p('aside.card_pixiv')
    iframe(src="https://cloud.mokeyjay.com/pixiv" frameborder="0" style="width:99%;height:380px;margin:0;")

    https://cloud.mokeyjay.com/pixiv 使用的是 超能小紫 提供的服务,也可以自行搭建,搭建方式请看这里

  2. 编辑BlogRoot/node_modules/hexo-theme-butterfly/layout/includes/widget/index.pug 文件,在你想要显示的位置插入以下代码:

    if theme.aside.card_pixiv
    !=partial('includes/widget/card_pixiv', {}, {cache:true})
  3. 编辑主题配置文件_config.butterfly.yml,在 card_webinfo 下面添加一行 card_pixiv: true,可以通过搜索关键词 aside,找到对应位置添加即可。不想显示,直接把文件中的 card_pixiv: true 改为 card_pixiv: false 即可。

  4. 编辑 BlogRoot/node_modules/hexo-theme-butterfly/languages/zh-CN.yml文件 (请根据你的网站语言选择),找到card_announcement: 公告,在下面添加一行card_pixiv: Pixiv日榜Top50(后面的文本可自定义)。

哔哩哔哩番剧页面插件

效果预览
查看步骤
关于图片加载相关问题

懒加载问题,此插件懒加载可能与你主题的懒加载存在冲突,以下为几种解决方法:

1.全站关闭懒加载,此插件启用/不启用懒加载均可正常运行;
2.如果主题提供单独页面的懒加载配置参数,可在插件配置的extra_option中配置为关。
3.[建议]关闭此插件的懒加载,并按照主题的懒加载图片格式配置srcValue和lazyloadAttrName,例butterfly主题:

bangumi:
enable: true
...
lazyload: false
srcValue: '__image__'
...

更多详情可见:关于图片加载相关问题

  1. 安装依赖

    npm install hexo-bilibili-bangumi --save
  2. 更新依赖库

    npm install hexo-bilibili-bangumi --update --save
  3. 注入哔哩哔哩番剧
    修改站点配置文件_config.yml,添加如下代码:

    bangumi:
    enable: true
    vmid: 321638084
    title: '生命不息,追番不止。'
    quote: 'Where there is life, there is life.'
    show: 1
    loading: '/img/bangumi-loading.gif'

    配置说明:

    • enable: 是否启用
    • vmid: 哔哩哔哩番剧页面的 vmid(uid), 如何获取?
    • title: 该页面的标题
    • quote: 写在页面开头的一段话,支持 html 语法
    • show: 初始显示页面:0: 想看 , 1: 在看 , 2: 看过,默认为 1
    • loading: 图片加载完成前的 loading 图片
  4. 执行Docs命令
    前往博客根目录,打开cmd命令窗口执行hexo new page bangumis

    hexo new page bangumis

    找到 BlogRoot/source/bangumis/index.md 这个文件,修改这个文件,添加 type: "bangumis"

    ---
    title: bangumis
    date: 2020-12-14 14:43:39
    type: "bangumis"
    ---

    防止请求次数过多插件不再自动获取番剧数据,所以请根据自己的需要在hexo generatehexo deploy之前使用hexo bangumi -u命令更新番剧数据。
    删除数据命令: hexo bangumi -d

  5. 获取 uid
    登录哔哩哔哩后前往 https://space.bilibili.com/xxx,网址最后的一串数字就是 uid。

添加卡通人物(看板娘)

效果预览
查看步骤

前往博客根目录,打开cmd命令窗口执行npm install --save hexo-helper-live2d

npm install --save hexo-helper-live2d

输入以下命令,下载相应的模型, 替换成你想要的模型名称即可,更多模型选择请点击此处,各个模型的预览请访问原作者

npm install --save live2d-widget-model-shizuku

修改站点配置文件_config.yml,添加如下代码:

live2d:
enable: true
scriptFrom: local # 默认
tagMode: false # 标签模式, 是否仅替换 live2d tag标签而非插入到所有页面中
debug: false # 调试, 是否在控制台输出日志
model:
use: live2d-widget-model-shizuku #模型选择
display:
position: right #模型位置
width: 150 #模型宽度
height: 300 #模型高度
hOffset: 20
vOffset: -20
mobile:
show: false #是否在手机端显示

重新编译运行,即可看到效果。

添加全局吸底APlayer

参考链接:Butterfly添加全局吸底Aplayer教程
此步骤适用于安装了hexo-tag-aplayer插件的人

效果预览
查看步骤
  1. 前往博客根目录,打开cmd命令窗口执行以下命令:

    npm i hexo-tag-aplayer --save
  2. 关闭asset_inject
    由于需要全局都插入 aplayer 和 meting 资源,为了防止插入重复的资源,需要把 asset_inject 设为false
    修改站点配置文件_config.yml,配置以下内容:

    aplayer:
    meting: true
    asset_inject: false
  3. 开启主题的aplayerInject
    修改主题配置文件_config.butterfly.yml,将enable设为trueper_page设为true

    # Inject the css and script (aplayer/meting)
    aplayerInject:
    enable: true
    per_page: true
  4. 插入Aplayer html
    为了适配hexo-tag-aplayer,主题内置的Meting js仍为1.2版本,并非最新的2.x版本。
    Aplayer html 例子(示例中没有显示歌词):

    <div class="aplayer no-destroy" data-id="7427714271" data-server="netease" data-type="playlist" data-fixed="true" data-mini="true" data-listFolded="false" data-order="random" data-lrctype="1" data-preload="none" data-autoplay="true" muted></div>

    参数解释如下表:

    optiondefaultdescription
    data-idrequiresong id / playlist id / album id / search keyword
    data-serverrequiremusic platform: netease, tencent, kugou, xiami, baidu
    data-typerequiresong, playlist, album, search, artist
    data-fixedfalseenable fixed mode
    data-minifalseenable mini mode
    data-autoplayfalseaudio autoplay
    data-theme#2980b9main color
    data-loopallplayer loop play, values: ‘all’, ‘one’, ‘none’
    data-orderlistplayer play order, values: ‘list’, ‘random’
    data-preloadautovalues: ‘none’, ‘metadata’, ‘auto’
    data-volume0.7default volume, notice that player will remember user setting, default volume will not work after user set volume themselves
    data-mutextrueprevent to play multiple player at the same time, pause other players when this player start play
    data-lrctype0lyric type
    data-listfoldedfalseindicate whether list should folded at first
    data-listmaxheight340pxlist max height
    data-storagenamemetingjslocalStorage key that store player setting

    require代表着这些参数是必须要使用的,其它的参数则可以根据自己需要配置。
    配置全局吸底,data-fixeddata-mini也必须配置,配置为true
    如果使用Pjax,则在class里需添加no-destroy,这样防止切换页面时Aplayer被销毁。

    将以下代码插入到主题配置文件(_config.butterfly.yml)的 “inject.bottom” 中
    inject:
    head:
    bottom:
    - <div class="aplayer no-destroy" data-id="7427714271" data-server="netease" data-type="playlist" data-fixed="true" data-mini="true" data-listFolded="false" data-order="random" data-lrctype="1" data-preload="none" data-autoplay="true" muted></div>
    运行Hexo就可以看到网页左下角出现了Aplayer。最后,如果你想切换页面时,音乐不会中断。请把主题配置文件的 “pjax” 设为 “true” 。
    pjax:
    enable: true
    exclude:
  5. UI 调整

    • 向上调整
      #toggle-sidebar {
      bottom: 80px
      }
      修改主题配置文件`_config.butterfly.yml`,将代码添加到 “inject.head” 中。
      inject:
      head:
      - '<style type="text/css">#toggle-sidebar {bottom: 80px}</style>'
    • 向右调整
      #toggle-sidebar {
      left: 100px
      }
      修改主题配置文件(_config.butterfly.yml),将代码添加到 “inject.head” 中。
      inject:
      head:
      - '<style type="text/css">#toggle-sidebar {left:100px}</style>'

添加贡献日历

效果预览
查看步骤

我的版本可能比较旧,贡献日历已经更新迭代了,所以直接参此教程:Gitcalendar

主页冒泡特效

效果预览
查看步骤

BlogRoot/node_modules/hexo-theme-butterfly/source/js目录下创建一个chocolate.js文件。

具体位置,请看下图所示:

直接复制导入如下代码:

/*
* @Author: tzy1997
* @Date: 2020-12-15 20:55:25
* @LastEditors: tzy1997
* @LastEditTime: 2021-01-12 19:02:25
*/

$(function() {
// 气泡
function bubble() {
$('#page-header').circleMagic({
radius: 10,
density: .2,
color: 'rgba(255,255,255,.4)',
clearOffset: 0.99
});
}! function(p) {
p.fn.circleMagic = function(t) {
var o, a, n, r, e = !0,
i = [],
d = p.extend({ color: "rgba(255,0,0,.5)", radius: 10, density: .3, clearOffset: .2 }, t),
l = this[0];

function c() { e = !(document.body.scrollTop > a) }

function s() { o = l.clientWidth, a = l.clientHeight, l.height = a "px", n.width = o, n.height = a }

function h() {
if (e)
for (var t in r.clearRect(0, 0, o, a), i) i[t].draw();
requestAnimationFrame(h)
}

function f() {
var t = this;

function e() { t.pos.x = Math.random() * o, t.pos.y = a 100 * Math.random(), t.alpha = .1 Math.random() * d.clearOffset, t.scale = .1 .3 * Math.random(), t.speed = Math.random(), "random" === d.color ? t.color = "rgba(" Math.floor(255 * Math.random()) ", " Math.floor(0 * Math.random()) ", " Math.floor(0 * Math.random()) ", " Math.random().toPrecision(2) ")" : t.color = d.color }
t.pos = {}, e(), this.draw = function() { t.alpha <= 0 && e(), t.pos.y -= t.speed, t.alpha -= 5e-4, r.beginPath(), r.arc(t.pos.x, t.pos.y, t.scale * d.radius, 0, 2 * Math.PI, !1), r.fillStyle = t.color, r.fill(), r.closePath() }
}! function() {
o = l.offsetWidth, a = l.offsetHeight,
function() {
var t = document.createElement("canvas");
t.id = "canvas", t.style.top = 0, t.style.zIndex = 0, t.style.position = "absolute", l.appendChild(t), t.parentElement.style.overflow = "hidden"
}(), (n = document.getElementById("canvas")).width = o, n.height = a, r = n.getContext("2d");
for (var t = 0; t < o * d.density; t++) {
var e = new f;
i.push(e)
}
h()
}(), window.addEventListener("scroll", c, !1), window.addEventListener("resize", s, !1)
}
}(jQuery);

// 调用气泡方法
bubble();
})

最后,在主题配置文件_config.butterfly.yml中,引入jquery.min.jschocolate.js

inject:
head:
# - <link rel="stylesheet" href="/xxx.css">
bottom:
- <script defer src="https://npm.elemecdn.com/jquery@latest/dist/jquery.min.js"></script>
- <script data-pjax defer src="https://npm.elemecdn.com/tzy-blog/lib/js/theme/chocolate.js"></script>

鼠标样式

效果预览
查看步骤

将以下代码复制到custom.css即可。

body {
cursor: url(https://bu.dusays.com/2022/05/17/6283c365d20dd.png), auto;
}

.hide-block>.hide-button.open,
.hide-inline>.hide-button.open {
display: block
}

a,
button,
img {
cursor: url(https://bu.dusays.com/2022/05/17/6283c376afcfc.png), auto
}

鼠标 * 字跟随掉落效果

效果预览
查看步骤

BlogRoot/node_modules/hexo-theme-butterfly/source/js目录下创建一个cursor.js文件。

/*!
* Fairy Dust Cursor.js
* - 90's cursors collection
* -- https://github.com/tholman/90s-cursor-effects
* -- http://codepen.io/tholman/full/jWmZxZ/
*/

(function fairyDustCursor() {

var possibleColors = ["#D61C59", "#E7D84B", "#1B8798"]
var width = window.innerWidth;
var height = window.innerHeight;
var cursor = { x: width / 2, y: width / 2 };
var particles = [];

function init() {
bindEvents();
loop();
}

// Bind events that are needed
function bindEvents() {
document.addEventListener('mousemove', onMouseMove);
document.addEventListener('touchmove', onTouchMove);
document.addEventListener('touchstart', onTouchMove);

window.addEventListener('resize', onWindowResize);
}

function onWindowResize(e) {
width = window.innerWidth;
height = window.innerHeight;
}

function onTouchMove(e) {
if (e.touches.length > 0) {
for (var i = 0; i < e.touches.length; i++) {
addParticle(e.touches[i].clientX, e.touches[i].clientY, possibleColors[Math.floor(Math.random() * possibleColors.length)]);
}
}
}

function onMouseMove(e) {
cursor.x = e.clientX;
cursor.y = e.clientY;
addParticle(cursor.x, cursor.y, possibleColors[Math.floor(Math.random() * possibleColors.length)]);
}

function addParticle(x, y, color) {
var particle = new Particle();
particle.init(x, y, color);
particles.push(particle);
}

function updateParticles() {
// Updated
for (var i = 0; i < particles.length; i++) {
particles[i].update();
}
// Remove dead particles
for (var i = particles.length - 1; i >= 0; i--) {
if (particles[i].lifeSpan < 0) {
particles[i].die();
particles.splice(i, 1);
}
}
}

function loop() {
requestAnimationFrame(loop);
updateParticles();
}

/**
* Particles
*/
function Particle() {
this.character = "*";
this.lifeSpan = 120; //ms
this.initialStyles = {
"position": "fixed",
"top": "0", //必须加
"display": "block",
"pointerEvents": "none",
"z-index": "10000000",
"fontSize": "20px",
"will-change": "transform"
};

// Init, and set properties
this.init = function(x, y, color) {
this.velocity = {
x: (Math.random() < 0.5 ? -1 : 1) * (Math.random() / 2),
y: 1
};
this.position = { x: x - 10, y: y - 20 };
this.initialStyles.color = color;
this.element = document.createElement('span');
this.element.innerHTML = this.character;
applyProperties(this.element, this.initialStyles);
this.update();
document.body.appendChild(this.element);
};
this.update = function() {
this.position.x += this.velocity.x;
this.position.y += this.velocity.y;
this.lifeSpan--;

this.element.style.transform = "translate3d(" this.position.x "px," this.position.y "px,0) scale(" (this.lifeSpan / 120) ")";
}
this.die = function() {
this.element.parentNode.removeChild(this.element);
}
}

// Applies css `properties` to an element.
function applyProperties(target, properties) {
for (var key in properties) {
target.style[key] = properties[key];
}
}

init();
})();

然后,在主题配置文件_config.butterfly.yml中,引入cursor.js文件。

滚动条

查看步骤

将以下代码复制到custom.css即可。

::-webkit-scrollbar {
width: 8px;
height: 8px
}

::-webkit-scrollbar-track {
border-radius: 2em;
/* background-color: rgba(73, 177, 245, .2); */
}

::-webkit-scrollbar-thumb {
background-color: rgb(255 255 255 / .3);
background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.1) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.1) 50%, rgba(255, 255, 255, 0.1) 75%, transparent 75%, transparent);
border-radius: 2em
}

::-webkit-scrollbar-corner {
background-color: transparent
}

手机侧边栏默认不展开

若主题版本大于 v4.0.0,可直接在子目录里添加 hide

menu:
Home: / || fas fa-home
Archives: /archives/ || fas fa-archive
Tags: /tags/ || fas fa-tags
Categories: /categories/ || fas fa-folder-open
List||fas fa-list||hide:
Music: /music/ || fas fa-music
Movie: /movies/ || fas fa-video
Link: /link/ || fas fa-link
About: /about/ || fas fa-heart

v3.7.1 版本中直接默认子目录是展开的,如果你想要隐藏,按下面步骤操作即可。

效果预览
查看步骤

BlogRoot/node_modules/hexo-theme-butterfly/source/js文件下新建 js 文件,并命名为 custom.js(命名按照自己喜好去命名,只需在主题配置文件_config.butterfly.yml中引入对应的js文件即可),将以下代码复制到新建的custom.js中。

/* 手机侧边栏默认不展开 */
var mobile_sidebar_menus = document.getElementById("sidebar-menus");
if (mobile_sidebar_menus) {
var menus_item_child = mobile_sidebar_menus.getElementsByClassName(
"menus_item_child"
);
var menus_expand = mobile_sidebar_menus.getElementsByClassName("expand");
for (var i = 0; i < menus_item_child.length; i++) {
menus_item_child[i].style.display = "none";
}
}

图库

图库页面只是普通的页面,你只需要hexo new page xxxxx 创建你的页面就行。

然后使用标签外挂 galleryGroup,具体用法请查看对应的内容。

<div class="gallery-group-main">
{% galleryGroup 'ACG' '那些二次元的故事' '/gallery/ACG' https://bu.dusays.com/2022/11/26/638228a86935a.webp %}
{% galleryGroup '岳阳' '2017年5月岳阳' '/gallery/YY' https://bu.dusays.com/2022/11/27/63831b681e9f8.jpg %}
{% galleryGroup 'OH MY GIRL' '关于OH MY GIRL的图片' '/Gallery/ohmygirl' https://i.loli.net/2019/12/25/hOqbQ3BIwa6KWpo.jpg %}
</div>

子页面

子页面也是普通的页面,你只需要hexo new page xxxxx 创建你的页面就行。

然后使用标签外挂 gallery,具体用法请查看对应的内容。

{% gallery %}
![](https://i.loli.net/2019/12/25/Fze9jchtnyJXMHN.jpg)
![](https://i.loli.net/2019/12/25/ryLVePaqkYm4TEK.jpg)
![](https://i.loli.net/2019/12/25/gEy5Zc1Ai6VuO4N.jpg)
![](https://i.loli.net/2019/12/25/d6QHbytlSYO4FBG.jpg)
![](https://i.loli.net/2019/12/25/6nepIJ1xTgufatZ.jpg)
![](https://i.loli.net/2019/12/25/E7Jvr4eIPwUNmzq.jpg)
![](https://i.loli.net/2019/12/25/mh19anwBSWIkGlH.jpg)
![](https://i.loli.net/2019/12/25/2tu9JC8ewpBFagv.jpg)
{% endgallery %}

如果你想要使用/photo/ohmygirl这样的链接显示你的图片内容

你可以把创建好的ohmygirl整个文件夹移到photo文件夹里去

Valine评论邮件回复提醒

由于 Valine 的国际版共享域名将于 2022 年 8 月 1 日起不再向中国大陆的最终用户提供服务,国际版共享域名仅服务于海外用户。本站已弃用 Valine ,改为 Twikoo。如果你更喜欢 Valine 的风格,你可以使用它的国区版。

参考教程

Hexo 优化 — Valine 扩展之邮件通知
Valine 添加验证码、博主标签及评论微信、QQ 通知

我的表情数据包

这里放上我的valine表情数据,展示如下图:

下载请点击下面按钮:

改写 menhera 表情样式

去除了dark模式下评论者头像的 border 和 padding(我是默认dark,如果不喜欢,则将css中的第一段去掉)。

因为 valine的默认宽度是 25px , 对于 menhera-chan 表情根本无法看清,所以将它pc端评论后的表情加载设置成300px,设屏宽小于768px的,让它继承继承父元素的100%宽 - 30px ,30px是为了与右侧有一段细微间隔,下图可以看到手机端的时候,表情和盒子最右侧是有一定距离的。

对于浏览选择 menhera-chan 表情时,宽度太小,看不清图片,所以这里调整为设备宽的 21%-22% 。QQ和B站表情保持不变,只对 menhera-chan 表情做出改善。

将以下代码复制到custom.css即可。

/* valine 评论 */

/* 去除了dark模式下头像border和padding */
[data-theme='dark'] .v[data-class=v] .vcards .vcard .vimg {
padding: 0;
border: none;
}

[data-theme='dark'] #post .v[data-class=v] .vcontent img {
display: inline-block;
}

.v[data-class=v] .emoji,
.v[data-class=v] .vemoji {
vertical-align: text-bottom;
}

.v[data-class=v] .vwrap .vemojis {
max-height: 260px !important;
}

.v[data-class=v] .vwrap .vemojis i[title|=menhera] {
width: 22% !important;
margin: 5px 10px;
}

.v[data-class=v] .vwrap .vemojis img[alt|=menhera] {
max-width: 100% !important;
}

.v[data-class=v] .vcontent .emoji[alt|=menhera],
.v[data-class=v] .vcontent .vemoji[alt|=menhera] {
max-width: 300px !important;
/* vertical-align: middle; */
margin: 8px 1px;
display: block !important;
}

@media screen and (max-width: 1200px) {
.v[data-class=v] .vwrap .vemojis i[title|=menhera] {
margin: 5px 8px;
}
}

@media screen and (max-width: 768px) {
.v[data-class=v] .vcontent .emoji[alt|=menhera],
.v[data-class=v] .vcontent .vemoji[alt|=menhera] {
max-width: calc(100% - 30px) !important;
}
}

@media screen and (max-width: 576px) {
.v[data-class=v] .vwrap .vemojis {
max-height: 200px !important;
}
.v[data-class=v] .vwrap .vemojis i[title|=menhera] {
margin: 5px 5px;
}
}

@media screen and (max-width: 400px) {
.v[data-class=v] .vwrap .vemojis i[title|=menhera] {
width: 21% !important;
}
}

效果如下:

添加[博主,小伙伴,访客]标签

  1. 打开BlogRoot/node_modules/hexo-theme-butterfly/layout/includes/third-party/comments/valine.pug,按指示添加如下字段。

    function initValine () {
    const valine = new Valine(Object.assign({
    el: '#vcomment',
    appId: '#{theme.valine.appId}',
    appKey: '#{theme.valine.appKey}',
    placeholder: '#{theme.valine.placeholder}',
    avatar: '#{theme.valine.avatar}',
    meta: '#{theme.valine.guest_info }'.split(','),
    pageSize: '#{theme.valine.pageSize}',
    lang: '#{theme.valine.lang}',
    recordIP: #{theme.valine.recordIP},
    serverURLs: '#{theme.valine.serverURLs}',
    emojiCDN: '#{theme.valine.emojiCDN}',
    emojiMaps: !{emojiMaps},
    enableQQ: #{theme.valine.enableQQ},
    path: window.location.pathname,
    requiredFields: [!{theme.valine.requiredFields ? JSON.stringify(theme.valine.requiredFields).split(',') : ''}],
    master: '#{theme.valine.master}'.split(','),
    friends: '#{theme.valine.friends}'.split(','),
    tagMeta: '#{theme.valine.tagMeta || "博主,小伙伴,访客"}'.split(','),
    metaPlaceholder: !{JSON.stringify(theme.valine.metaPlaceholder || {})},
    visitor: #{theme.valine.visitor}
    }, !{JSON.stringify(theme.valine.option)}))
    }

    如图所示:

  2. 修改主题配置文件_config.butterfly.ymlvaline属性。

    • valine配置项添加 md5加密的博主邮箱,小伙伴邮箱

      # valine
      # https://valine.js.org
      valine:
      appId: # leancloud application app id
      appKey: # leancloud application app key
      pageSize: 10 # comment list page size
      avatar: monsterid # gravatar style https://valine.js.org/#/avatar
      lang: zh-CN # i18n: zh-CN/zh-TW/en/ja
      placeholder: # valine comment input placeholder (like: Please leave your footprints)
      guest_info: nick,mail,link # valine comment header info (nick/mail/link)
      recordIP: false # Record reviewer IP
      serverURLs: # This configuration is suitable for domestic custom domain name users, overseas version will be automatically detected (no need to manually fill in)
      bg: # valine background
      emojiCDN: # emoji CDN
      enableQQ: true # enable the Nickname box to automatically get QQ Nickname and QQ Avatar
      requiredFields: nick,mail # required fields (nick/mail)
      master: # md5加密后的博主邮箱
      - d4e7????????????44a14e9a94 #可添加多个
      friends: # md5加密后的小伙伴邮箱
      - 5c?????????????e268ad3819c #可添加多个
      - 7c?????????????e2????3919c
      tagMeta: '博主,小伙伴,访客' # 标签要显示的文字,默认'博主,小伙伴,访客'
      metaPlaceholder:
      nick: 昵称/QQ号(必填)
      mail: 邮箱(必填)
      link: 网址(https://)

      如图所示:

    • 在主题配置文件_config.butterfly.yml的CDN配置项添加如下内容。将Valine.min.js替换成魔改版本。

          CDN:
      # comments
      gitalk: https://fastly.jsdelivr.net/npm/gitalk@latest/dist/gitalk.min.js
      gitalk_css: https://fastly.jsdelivr.net/npm/gitalk/dist/gitalk.min.css
      - valine: https://fastly.jsdelivr.net/npm/valine/dist/Valine.min.js
      valine: https://fastly.jsdelivr.net/gh/tzy13755126023/BLOG_SOURCE/valine_f/valine.min.js

valine获取评论失败

如下图:

这里并没有加载和渲染 valine 评论数据 , 但在 LeanCloud 数据存储中 是存在评论数据的。

原因 :LeanCloud 国际版通用域名失效

打开控制台发现https://us.avoscloud.com/1.1/classes/Comment?xxxxx已经请求失败(net::ERR_NAME_NOT_RESOLVED),域名也无法ping通。

解决办法:

将 Valine 指定 自定义服务器URL。在主题配置里的 Valine 的 serverURLs 填入https://xxxxxxxx.api.lncldglobal.com。自定义服务器的URL需要到 LeanCloud后台 查看。打开后台之后进入 Settings - App Keys ,Request domain 里面的xxxxxxxx.api.lncldglobal.com就是你需要指定的服务器URL。xxxxxxxx 就是 AppID的前8位字符。

如下图:

经 postman 测试 ,https://xxxxxxxx.api.lncldglobal.com/1.1/classes/Comment?x=x&xx=xx该接口会正常返回评论数据。

关于valine评论,这里会抽空写一篇详细的教程,敬请期待。

首页分类磁铁

原教程:Categories Magnet

效果预览
插件版教程(推荐👍)
  1. 安装依赖,前往博客根目录,打开cmd命令窗口执行如下命令:
    npm install hexo-butterfly-categories-card --save
  2. 添加配置信息,在站点配置文件_config.yml或者主题配置文件_config.butterfly.yml中添加
    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: Ubuntu指南
    cover: https://assets.akilar.top/image/cover1.webp
    - descr: 玩转Win10
    cover: https://assets.akilar.top/image/cover2.webp
    - descr: 长篇小说连载
    cover: https://assets.akilar.top/image/cover3.webp
    - descr: 个人日记
    cover: https://assets.akilar.top/image/cover4.webp
    - descr: 诗词歌赋
    cover: https://assets.akilar.top/image/cover5.webp
    - descr: 杂谈教程
    cover: https://assets.akilar.top/image/cover6.webp
    custom_css: https://npm.elemecdn.com/hexo-butterfly-categories-card@1.0.0/lib/categorybar.css
  3. 参数意义
    参数备选值/类型释义
    prioritynumber【可选】过滤器优先级,数值越小,执行越早,默认为10,选填
    enabletrue/false【必选】控制开关
    enable_pagepath/all【可选】填写想要应用的页面的相对路径(即路由地址),如根目录就填’/‘,分类页面就填’/categories/‘。若要应用于所有页面,就填’all’,默认为’/‘
    layout.typeid/class【可选】挂载容器类型,填写id或class,不填则默认为id
    layout.nametext【必选】挂载容器名称
    layout.index0和正整数【可选】前提是layout.type为class,因为同一页面可能有多个class,此项用来确认究竟排在第几个顺位
    columnodd/even【可选】显示列数,考虑到比例问题,只提供3列和4列,odd为3列, even为4列
    rownumber【可选】显示行数,默认两行,超过行数切换为滚动显示
    message.descrtext分类描述,需要和你自己的文章分类一一对应。
    message.coverurl分类背景,需要和你自己的文章分类一一对应。
    custom_cssurl【可选】自定义样式,会替换默认的css链接,可以下载文档给出的cdn链接后自主修改
旧版教程(不推荐)
  1. 修改BlogRoot/node_modules/hexo-theme-butterfly/layout/index.pug
    extends includes/layout.pug
    block content
    include ./includes/mixins/post-ui.pug
    #recent-posts.recent-posts
    if theme.categoryBar.enable
    .recent-post-item(style='height:auto;width:100%;padding:0px;')
    #categoryBar!= list_categories(site.categories,{class: 'categoryBar',depth: 1})
    +postUI
    include includes/pagination.pug
  2. 新建BlogRoot/node_modules/hexo-theme-butterfly/source/css/_layout/categoryBar.styl
    if hexo-config('categoryBar.enable')
    #categoryBar
    width 100%!important
    ul
    &.categoryBar-list
    margin 5px 5px 0 5px!important
    padding 0!important

    li
    &.categoryBar-list-item
    font-weight bold
    display inline-block
    height 180px!important
    margin 5px .5% 0 .5%!important
    background-image linear-gradient(rgba(0, 0, 0, 0.4) 25%, rgba(16, 16, 16, 0) 100%)
    border-radius 10px
    padding 25px 0 25px 25px!important
    box-shadow rgba(50, 50, 50, 0.3) 50px 50px 50px 50px inset
    overflow hidden
    background-size 100%!important
    background-position center!important
    &:hover
    background-size 110%!important
    box-shadow inset 500px 50px 50px 50px rgba(50,50,50, 0.6)
    span
    &.categoryBar-list-count
    &::after
    transition all .5s
    transform translate(-100%, 0)
    a
    &.categoryBar-list-link
    color white!important
    font-size 20px!important
    &::before
    content '|'!important
    color white!important
    font-size 20px!important
    &:after
    content ''
    position relative
    width 0
    bottom 0
    display block
    height 3px
    border-radius 3px
    background-color white
    &:hover
    &:after
    width 90%
    left 1%
    transition all 0.5s

    span
    &.categoryBar-list-count
    display block!important
    color white!important
    font-size 20px!important
    &::before
    content '\f02d'!important
    padding-right 15px!important
    @extend .fontawesomeIcon
    &::after
    padding 5px
    display block!important
    color white!important
    font-size 20px!important
    position relative
    right -100%
    covers = hexo-config('categoryBar.cover')
    for cover,i in covers
    li.categoryBar-list-item:nth-child({i+1})
    background unquote(cover)
    descrs = hexo-config('categoryBar.descr')
    for descr,i in descrs
    li.categoryBar-list-item:nth-child({i+1})>span::after
    content descr!important
    if hexo-config('categoryBar.column') == 'odd'
    li
    &.categoryBar-list-item
    width 32.3%!important
    else if hexo-config('categoryBar.column') == 'even'
    li
    &.categoryBar-list-item
    width 24%!important
    @media screen and (max-width: 650px)
    li
    &.categoryBar-list-item
    width 48%!important
    height 150px!important
    margin 5px 1% 0 1%!important

    $caterow = hexo-config('categoryBar.row')?hexo-config('categoryBar.row'):2
    .categoryBar-list
    max-height 190px * $caterow
    overflow auto
    &::-webkit-scrollbar
    width 0!important
    @media screen and (max-width: 650px)
    .categoryBar-list
    max-height 160px * $caterow
  3. 在主题配置文件_config.butterfly.yml中添加配置项:
    categoryBar:
    enable: true
    column: odd # 显示列数,odd:3列 | even:4列
    row: 2 #显示行数,默认两行,超过行数切换为滚动显示
    descr:
    - Good things to share
    - Back end talk
    - personal diary
    - Front end serialization
    - Butterfly theme
    - Other items
    cover:
    - url('https://fastly.jsdelivr.net/npm/akilar-candyassets/image/cover1.webp')
    - '#abcdef' # HEX格式色值需要用''包裹,不然会被识别成注释
    - rgba(45,67,89,0.7)
    - linear-gradient(rgba(0, 0, 0, 0.4) 25%, rgba(200,16 , 16, 0) 100%)
    - url('https://fastly.jsdelivr.net/npm/akilar-candyassets/image/cover5.webp')
    - url('https://fastly.jsdelivr.net/npm/akilar-candyassets/image/cover6.webp')

侧边栏电子时钟

效果预览
查看步骤 (新版,推荐👍)

✨可参考教程✨:给butterfly添加侧边栏电子钟

  1. 如果跑过下面旧版的教程,前往博客根目录,卸载原版电子钟插件,打开cmd命令窗口执行如下命令:
    npm uninstall hexo-butterfly-clock
  2. 安装新的插件,前往博客根目录,打开cmd命令窗口执行如下命令:
    npm install hexo-butterfly-clock-anzhiyu --save
  3. 在站点配置文件_config.yml 或 主题配置文件_config.butterfly.yml 中添加配置信息
    electric_clock:
    enable: true # 开关
    priority: 5 #过滤器优先权
    enable_page: all # 应用页面
    exclude:
    # - /posts/
    # - /about/
    layout: # 挂载容器类型
    type: class
    name: sticky_layout
    index: 0
    loading: https://cdn.cbd.int/hexo-butterfly-clock-anzhiyu/lib/loading.gif #加载动画自定义
    clock_css: https://cdn.cbd.int/hexo-butterfly-clock-anzhiyu/lib/clock.min.css
    clock_js: https://cdn.cbd.int/hexo-butterfly-clock-anzhiyu/lib/clock.min.js
    ip_api: https://widget.qweather.net/simple/static/js/he-simple-common.js?v=2.0
    # 和风天气key 默认是 b16a1fa0e63c46a4b8f28abfb06ae3fe
    qweather_key: # 你的key
    # 高得地图web服务key 默认为 e2b04289e870b005374ee030148d64fd&s=rsv3
    gaud_map_key: # 你的key
    default_rectangle: false # 开启后将一直显示rectangle位置的天气,否则将获取访问者的地理位置与天气
    rectangle: 112.982279,28.19409 # 获取访问者位置失败时会显示该位置的天气,同时该位置为开启default_rectangle后的位置
  4. 具体参数含义
    点击查看具体参数
    参数备选值/类型释义
    prioritynumber【可选】过滤器优先级,数值越小,执行越早,默认为 10,选填
    enabletrue/false【必选】控制开关
    enable_pagepath/all【可选】填写想要应用的页面的相对路径(即路由地址),如根目录就填’/‘,分类页面就填’/categories/‘。若要应用于所有页面,就填’all’,默认为 all
    excludepath【可选】填写想要屏蔽的页面,可以多个。写法见示例。原理是将屏蔽项的内容逐个放到当前路径去匹配,若当前路径包含任一屏蔽项,则不会挂载。
    layout.typeid/class【可选】挂载容器类型,填写 id 或 class,不填则默认为 id
    layout.nametext【必选】挂载容器名称
    layout.index0 和正整数【可选】前提是 layout.type 为 class,因为同一页面可能有多个 class,此项用来确认究竟排在第几个顺位
    loadingURL【可选】电子钟加载动画的图片
    clock_cssURL【可选】电子钟样式 CDN 资源
    clock_jsURL【可选】电子钟执行脚本 CDN 资源
    ip_apiURL【可选】获取时钟 IP 的 API
    qweather_keytext【可选】和风天气 key
    gaud_map_keytext【可选】高得地图 web 服务 key
    default_rectangletext【可选】开启后将一直显示 rectangle 位置的天气,否则将获取访问者的地理位置与天气
    rectangletext【可选】获取访问者位置失败时会显示该位置的天气,同时该位置为开启 default_rectangle 后的位置

【qweather_key】和【gaud_map_key】建议自己申请。

qweather_key 申请流程
  1. qweather_key 传送门
  2. 登录后进入控制台(可能要绑定邮箱和手机)
  3. 创建项目,项目名称(名字随意)、勾选【免费订阅】、适用平台【 Web API】、KEY的名称(随意填),最后点击【创建】
  4. 可在项目管理中,到对应的【key】
gaud_map_key 申请流程
  1. gaud_map_key 传送门
  2. 登录后完成一些认证(个人开发),进入控制台
  3. 创建应用,应用名称随意,类型选其他
  4. 点击【添加】,【key名称】随便填,【服务平台】选择 Web服务,点击提交,就得到【key】了
查看步骤(旧版,不建议)

✨参考教程✨: Sidebar Card Clock

  1. 安装依赖,前往博客根目录,打开cmd命令窗口执行如下命令:
    npm install hexo-butterfly-clock --save 
  2. 在站点配置文件_config.yml添加配置项:
    # electric_clock
    electric_clock:
    enable: true # 开关
    priority: 5 #过滤器优先权
    enable_page: all # 应用页面
    exclude:
    # - /posts/
    # - /about/
    layout: # 挂载容器类型
    type: class
    name: sticky_layout
    index: 0
    loading: https://fastly.jsdelivr.net/gh/tzy13755126023/BLOG_SOURCE/theme_f/loading.gif #加载动画自定义

更换字体

查看步骤

添加下面这段css即可。

@font-face {
font-family: 'tzy';
/* 字体名自定义即可 */
/* src: url('https://cdn.jsdelivr.net/gh/tzy13755126023/BLOG_SOURCE/font/ZhuZiAWan.woff2'); */
src: url('https://npm.elemecdn.com/ethan4116-blog/lib/font/ZhuZiAWan.ttf');
/* 字体文件路径 */
font-display: swap;
}

body,
.gitcalendar {
font-family: tzy !important;
}

局部css优化

查看代码

.categoryBar-list {
max-height: 400px;
}

.clock-row {
overflow: hidden;
text-overflow: ellipsis;
}

/*3s为加载动画的时间,1为加载动画的次数,ease-in-out为动画效果*/

#page-header,
#web_bg {
-webkit-animation: imgblur 2s 1 ease-in-out;
animation: imgblur 2s 1 ease-in-out;
}

@keyframes imgblur {
0% {
filter: blur(5px);
}
100% {
filter: blur(0px);
}
}

/*适配使用-webkit内核的浏览器 */

@-webkit-keyframes imgblur {
0% {
-webkit-filter: blur(5px);
}
100% {
-webkit-filter: blur(0px);
}
}
.table-wrap img {
margin: .6rem auto .1rem !important;
}

/* 标签外挂 网站卡片 start */

.site-card-group img {
margin: 0 auto .1rem !important;
}

.site-card-group .info a img {
margin-right: 10px !important;
}

[data-theme='dark'] .site-card-group .site-card .info .title {
color: #f0f0f0 !important;
}

[data-theme='dark'] .site-card-group .site-card .info .desc {
color: rgba(255, 255, 255, .7) !important;
}

.site-card-group .info .desc {
margin-top: 4px !important;
}
/* 代码块颜色 */

figure.highlight pre .addition {
color: #00bf03 !important;
}

禁止右键及F12等事件

效果预览
查看步骤 (新版,推荐👍)

旧版教程(已弃用),对于高版本浏览器,可以先打开控制台再进入站点(亲测 Google Chrome v100),因此本站已弃用forbidden_control(),可直接删除。引入的 function.min.css 也可以删除。

下面开始新的教程,如果你不需要 禁用控制台 以及 禁用一些特殊 keyCode 事件 ,可直接忽略。

  1. 修改【BlogRoot/node_modules/hexo-theme-butterfly/layout/includes/layout.pug】,根据图中位置添加以下 pug 代码(跟 headbody同级)。
    script.
    ((function() {var callbacks = [],timeLimit = 50,open = false;setInterval(loop, 1);return {addListener: function(fn) {callbacks.push(fn);},cancleListenr: function(fn) {callbacks = callbacks.filter(function(v) {return v !== fn;});}}
    function loop() {var startTime = new Date();debugger;if (new Date() - startTime > timeLimit) {if (!open) {callbacks.forEach(function(fn) {fn.call(null);});}open = true;window.stop();alert('你真坏,请关闭控制台!');document.body.innerHTML = "";} else {open = false;}}})()).addListener(function() {window.location.reload();});
    script.
    function toDevtools(){
    let num = 0;
    let devtools = new Date();
    devtools.toString = function() {
    num++;
    if (num > 1) {
    alert('你真坏,请关闭控制台!')
    window.location.href = "about:blank"
    blast();
    }
    }
    console.log('', devtools);
    }
    toDevtools();
  2. 将以下代码复制到自定义的custom.js
    document.onkeydown = function (e) {
    if (123 == e.keyCode || (e.ctrlKey && e.shiftKey && (74 === e.keyCode || 73 === e.keyCode || 67 === e.keyCode)) || (e.ctrlKey && 85 === e.keyCode)) return btf.snackbarShow("你真坏,不能打开控制台喔!"), event.keyCode = 0, event.returnValue = !1, !1
    };
  3. 重新编译运行,即可看到效果。
  4. 注意: 如果自己调试阶段,可注释第一步和第二步中的代码,再进行编译,就可以打开控制台了。部署时放开注释,编译好再丢上去就OK了。
查看步骤 (旧版,已弃用)
  1. 在 主题配置 的 inject 的 head 里 引入 这个 css。

    <link rel="stylesheet" href="https://fastly.jsdelivr.net/gh/tzy13755126023/BLOG_SOURCE/css/function.min.css">
  2. 将以下代码复制到自定义的custom.js, 执行 forbidden_control() 执行即可看到效果。

    function forbidden_control() {
    $.extend({
    message: function(a) {
    var b = {
    title: "",
    message: "操作成功",
    time: "3000",
    type: "success",
    showClose: !0,
    autoClose: !0,
    onClose: function() {}
    };
    "string" == typeof a && (b.message = a), "object" == typeof a && (b = $.extend({}, b, a));
    var c, d, e, f = b.showClose ? '<div class="c-message--close">×</div>' : "",
    g = "" !== b.title ? '<h2 class="c-message__title">' b.title "</h2>" : "",
    h = '<div class="c-message animated animated-lento slideInRight"><i class=" c-message--icon c-message--' b.type '"></i><div class="el-notification__group">' g '<div class="el-notification__content">' b.message "</div>" f "</div></div>",
    i = $("body"),
    j = $(h);
    d = function() {
    j.addClass("slideOutRight"), j.one("webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend", function() {
    e()
    })
    }, e = function() {
    j.remove(), b.onClose(b), clearTimeout(c)
    }, $(".c-message").remove(), i.append(j), j.one("webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend", function() {
    j.removeClass("messageFadeInDown")
    }), i.on("click", ".c-message--close", function(a) {
    d()
    }), b.autoClose && (c = setTimeout(function() {
    d()
    }, b.time))
    }
    }),
    document.onkeydown = function(e) {
    if (123 == e.keyCode || e.ctrlKey && e.shiftKey && (74 === e.keyCode || 73 === e.keyCode || 67 === e.keyCode) || (e.ctrlKey && 85 === e.keyCode)) return $.message({
    message: "采用本站js及css请注明来源,禁止商业使用!",
    title: "你真坏,不能打开控制台喔!",
    type: "error",
    autoHide: !1,
    time: "3000"
    }), event.keyCode = 0, event.returnValue = !1, !1
    }, document.oncontextmenu = function() {
    return $.message({
    message: "采用本站js及css请注明来源,禁止商业使用!",
    title: "不能右键/长按喔!",
    type: "error",
    autoHide: !1,
    time: "3000"
    }), !1
    }
    }

部分动效说明

查看步骤

请移步此博文 : 特效标签 wow.js

部分页面插入视频

效果预览

实际视频效果请移步: 留言板友链

查看步骤
  1. 替换文件或修改文件。
    如果你所使用的主题版本是 3.7.1 ,可直接下载文件,将BlogRoot/node_modules/hexo-theme-butterfly/source/css/_layout/head.styl替换成新下载的head.styl,将BlogRoot/node_modules/hexo-theme-butterfly/layout/includes/header/index.pug替换成新下载的index.pug
    如果你所使用的主题版本跟本站(v3.7.1)有所出入,请对比一下两个文件(下载的文件和你的主题文件)之间的差异,可能需要你对BlogRoot/node_modules/hexo-theme-butterfly/source/css/_layout/head.styl该文件做出一些修改:
    &.not-home-page
    height: 20rem

    +maxWidth768()
    height: 14rem !important

    #page-site-info
    position: absolute
    top: 10rem
    padding: 0 .5rem
    width: 100%
    z-index: 2

    +maxWidth768()
    top: 7rem !important

    #post-info
    position: absolute
    ... ...

    &.has-video
    position: relative
    height: 80vh !important

    #page-site-info
    top: 50% !important
    margin-top: -1.425em

    +maxWidth768()
    top: 7rem !important
    margin-top: 0

    +maxWidth768()
    height: 14rem !important

    &.not-top-img
    margin-bottom: .5rem
    ... ...
    主要针对not-home-page#page-site-info修改一些属性,并新增了一个名为has-video的类。
  2. 在自定义 css 中加入以下样式。也可以直接将这段换成style格式写进 head.styl
    #index-video {
    z-index: 0;
    position: absolute;
    top: 0;
    left: 0;
    height: 80vh;
    width: 100%;
    object-fit: cover;
    }
    @media only screen and (max-width: 768px) {
    #index-video {
    display: none;
    }
    }

    @media only screen and (min-width: 768px) {
    .bg-cover {
    background-image: none !important;
    }
    }
  3. 在想插入视频的页面,一定要有某个属性 ,可自行配置 ,如果用 type , 则BlogRoot/node_modules/hexo-theme-butterfly/layout/includes/header/index.pug中则根据对应的 type 类型去写逻辑即可。
    比如我的 BlogRoot/source/comment/index.md 配置如下:
    ---
    title: 留言板
    type: 'comment'
    ---
    所以在BlogRoot/node_modules/hexo-theme-butterfly/layout/includes/header/index.pug中的第 23 行加入 page.type == 'comment'
    - var isHomeClass = is_home() ? 'full_page' : (page.type == 'comment' || page.type == 'link' ) ? 'not-home-page has-video bg-cover' : 'not-home-page'
    第 51 - 56 行 加入
    if page.type == 'comment' 
    video#index-video(autoplay='' loop='' muted='')
    source(src='你的视频地址')
    if page.type == 'link'
    video#index-video(autoplay='' loop='' muted='')
    source(src='你的视频地址')
  4. 如果已经用了主页冒泡特效,请将下面这段代码替换之前的chocolate.js。没有使用即可忽略这步。
    /*
    * @Author: tzy1997
    * @Date: 2020-12-15 20:55:25
    * @LastEditors: tzy1997
    * @LastEditTime: 2021-11-25 18:15:47
    */
    // TODO 获取窗口高度 11-19
    var b_h = $(window).height()
    var b_w = $(window).width()

    $(function() {

    // 气泡
    function bubble() {
    $('#page-header').circleMagic({
    radius: 10,
    density: .2,
    color: 'rgba(255,255,255,.4)',
    clearOffset: 0.99
    });
    }! function(p) {
    p.fn.circleMagic = function(t) {
    var o, a, n, r, e = !0,
    i = [],
    d = p.extend({ color: "rgba(255,0,0,.5)", radius: 10, density: .3, clearOffset: .2 }, t),
    l = this[0];

    function c() { e = !(document.body.scrollTop > a) }

    function s() {
    // TODO 获取窗口高度 ethan_tzy
    var a_c = l.clientHeight
    if ($('#index-video').length > 0 && b_w > 768) {
    a = b_h * 0.8
    } else {
    a = a_c
    }
    // o = l.clientWidth, a = l.clientHeight, l.height = a "px", n.width = o, n.height = a
    o = l.clientWidth, l.height = a "px", n.width = o, n.height = a
    }

    function h() {
    if (e)
    for (var t in r.clearRect(0, 0, o, a), i) i[t].draw();
    requestAnimationFrame(h)
    }

    function f() {
    var t = this;

    function e() { t.pos.x = Math.random() * o, t.pos.y = a 100 * Math.random(), t.alpha = .1 Math.random() * d.clearOffset, t.scale = .1 .3 * Math.random(), t.speed = Math.random(), "random" === d.color ? t.color = "rgba(" Math.floor(255 * Math.random()) ", " Math.floor(0 * Math.random()) ", " Math.floor(0 * Math.random()) ", " Math.random().toPrecision(2) ")" : t.color = d.color }
    t.pos = {}, e(), this.draw = function() { t.alpha <= 0 && e(), t.pos.y -= t.speed, t.alpha -= 5e-4, r.beginPath(), r.arc(t.pos.x, t.pos.y, t.scale * d.radius, 0, 2 * Math.PI, !1), r.fillStyle = t.color, r.fill(), r.closePath() }
    }! function() {
    // TODO 气泡的高度 11-19
    var a_c = l.clientHeight
    if ($('#index-video').length > 0 && b_w > 768) {
    a = b_h * 0.8
    } else {
    a = a_c
    }
    o = l.offsetWidth,
    // o = l.offsetWidth, a = l.offsetHeight,
    function() {
    var t = document.createElement("canvas");
    t.id = "canvas", t.style.top = 0, t.style.zIndex = 0, t.style.position = "absolute", l.appendChild(t), t.parentElement.style.overflow = "hidden"
    }(), (n = document.getElementById("canvas")).width = o, n.height = a, r = n.getContext("2d");
    for (var t = 0; t < o * d.density; t++) {
    var e = new f;
    i.push(e)
    }
    h()
    }(), window.addEventListener("scroll", c, !1), window.addEventListener("resize", s, !1)
    }
    }(jQuery);
    bubble();
    })
  5. 重新编译运行,即可看到效果。

公告栏两个小人

效果预览
查看步骤

在【BlogRoot/node_modules/hexo-theme-butterfly/layout/includes/widget/card_announcement.pug】下添加如下部分代码。

注意: 将代码复制到【card_announcement.pug】文件以后,不难发现会有重复的一段代码。你要做的一步操作是,删除重复的代码(优先保留你主题版本原有的代码), 这里之所以没用 Diff 代码块,是因为怕删除【+】号的时候在格式上特别容易出错。

if theme.aside.card_announcement.enable
.card-widget.card-announcement
.item-headline
i.fas.fa-bullhorn.card-announcement-animation
span= _p('aside.card_announcement')
.announcement_content!= theme.aside.card_announcement.content
.xpand(style='height:200px;')
canvas.illo(width='800' height='800' style='max-width: 200px; max-height: 200px; touch-action: none; width: 640px; height: 640px;')
script(src='https://npm.elemecdn.com/ethan4116-blog/lib/js/other/two-people/twopeople1.js')
script(src='https://npm.elemecdn.com/ethan4116-blog/lib/js/other/two-people/zdog.dist.js')
script#rendered-js(src='https://npm.elemecdn.com/ethan4116-blog/lib/js/other/two-people/twopeople.js')
style.
.card-widget.card-announcement {
margin: 0;
align-items: center;
justify-content: center;
text-align: center;
}
canvas {
display: block;
margin: 0 auto;
cursor: move;
}

星空背景和流星特效

查看步骤
  1. BlogRoot/node_modules/hexo-theme-butterfly/source/js目录下新建universe.js,输入以下代码:
    function dark() {window.requestAnimationFrame=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame;var n,e,i,h,t=.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=.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(.2,1-.4*(this.comet+1-1)),this.do=l(5e-4,.002)+.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()
  2. BlogRoot/node_modules/hexo-theme-butterfly/source/css目录下新建universe.css,输入以下代码:
    /* 背景宇宙星光  */
    #universe{
    display: block;
    position: fixed;
    margin: 0;
    padding: 0;
    border: 0;
    outline: 0;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    z-index: -1;
    }
  3. 在主题配置文件_config.butterfly.ymlinject配置项中bottom下填入:
    inject:
    bottom:
    # 星空背景
    - <canvas id="universe"></canvas>
    - <script defer src="/js/universe.js"></script>
  4. 在主题配置文件_config.butterfly.ymlinject配置项中head下填入:
    inject:
    head:
    ## 星空背景
    - <link rel="stylesheet" href="/css/universe.css">
  5. 重新编译即可看到效果。

樱花飘落效果

效果预览
查看步骤

在主题配置文件_config.butterfly.ymlinject配置项中bottom下引入sakura.js即可。

inject:
bottom:
# 樱花飘落效果
# - <script async src="https://npm.elemecdn.com/tzy-blog/lib/js/other/sakura.js"></script>

灯笼特效

外挂标签

添加github徽标

自定义右键菜单

参考方向 教程原贴
TZY Hexo Butterfly 自定义右键菜单(基础)
ZHHEO Butterfly 魔改:自定义右键菜单
LYX 博客自定义右键菜单升级版

加载动画

可参考 Loading Animation

评论弹幕

参考教程 Butterfly 主题的留言弹幕界面增强版(支持 Twikoo、Waline、Valine)

自定义页脚

效果预览
查看教程

侧边栏公众号

效果预览
查看教程

文章加密插件

效果预览

点击 Demo Page , 所有的密码都是 【hello】。

查看教程

详见开源地址:hexo-blog-encrypt

  1. 在根目录执行以下命令
    npm install --save hexo-blog-encrypt
  2. Front matter配置方法
    ---
    title: Hello World
    tags:
    - 作为日记加密
    date: 2016-03-30 21:12:21
    password: mikemessi
    abstract: 有东西被加密了, 请输入密码查看.
    message: 您好, 这里需要密码.
    theme: xray
    wrong_pass_message: 抱歉, 这个密码看着不太对, 请再试试.
    wrong_hash_message: 抱歉, 这个文章不能被校验, 不过您还是能看看解密后的内容.
    ---
  3. 可以在线挑选你喜欢的主题,并应用到你的博客中: defaultblinkshrinkflipupsurgewavexray
  4. 重新编译项目并进入对应的文章页即可看到加密效果

友链朋友圈

效果预览

效果请移步:朋友圈

查看教程