我是基于Kimi moonshot-v1-8k实现的AI助手,在此博客上负责整理和概括文章
本文详细记录了作者在搭建Hexo博客Butterfly主题时遇到的问题及解决方案。主要内容包括:1. 设置随机主题背景,包括文章封面、小站背景和磁贴封面背景,通过静态和动态JS脚本实现;2. 遇到的问题及解决方法,如自动部署缓存问题、插件bug等;3. 自定义樱花飘落脚本和相册界面魔改,通过注入JS和CSS样式实现。文章还记录了编辑和更新历程,为搭建Hexo博客提供了实用参考。同时,介绍了移动端背景图片显示不全的CSS代码改进、Aplayer播放器的魔改、解决anzhiyu版本的bug、配置music的md文件、调整CSS样式、添加音乐界面标题处理等技术细节。文章还探讨了随机磁贴封面的bug修复、阅读进度按钮问题、夜间模式切换和gulp全局资源压缩等优化措施。最后,文章提到了完善音乐界面和修改bug的过程,包括增加卡片选择主题歌单、解决公式渲染和pdf显示问题,以及修复音乐播放界面的bug。此外,文章还介绍了如何优化看板娘样式的步骤,包括Fork原项目、创建新分支、本地修改代码、更新CDN内容、自定义看板娘样式等,实现了看板娘的个性化设置和功能优化。整体上,本文详细记录了网站优化和bug修复的过程,为搭建Hexo博客提供了宝贵的经验和参考。
编辑记录
2024-10-22 第一次编辑
- 设置随机背景和一些小坑
2024-10-25 第二次编辑
- 其他碎碎念
2024-11-16 第三次编辑
- 完善音乐界面
2024-11-23 第四次编辑
- 解决一些 bug
2024-12-09 第五次编辑
- 优化看板娘
本文章是作为此次开发个人 Hexo 博客过程遇到的坑及其解决方法的总结。
# 怎么设置随机主题背景
# 随机文章封面背景
随机文章封面的实现使用的是 hexo 后端静态的 js 脚本实现,在 \themes\butterfly\scripts
中新建 random_img.js
,每当重新 hexo 三连时,都会执行这里的 js,不过是静态的,不能动态变化,即不能刷新网页执行。
该脚本的思路是:通过 hexo.theme.config.xxx
来读取主题配置文件 ( _config.butterfly.yml
) 的对应参数,这里是 mytheme
,读取之后根据是否有值来决定根据日期随机还是选择某个确定主题。
该脚本不需要 inject 注入,这里设置文章封面本质还是获取了主题配置文件的 cover
参数进行封面设置。
# 随机小站背景
设置随机背景,使用的是前端能动态刷新的 js 脚本实现,并与后端 js 进行通信传递参数,在 \themes\butterfly\source\js
中新建 randombg.js
,此为前端脚本,负责刷新封面;在 \themes\butterfly\scripts
中新建 setbgtheme.js
,此为后端脚本,负责获取主题配置文件参数,并传递到前端 js。
setbgtheme.js
的代码如下:
tabs setbgtheme, 2
hexo.extend.filter.register('after_render:html', (str) => { | |
const bgtheme = hexo.theme.config.bgtheme; | |
return str.replace('</head>', ` | |
<script> | |
window.bgtheme = "${bgtheme}"; | |
</script> | |
</head>`); | |
}); |
hexo.extend.filter.register('after_render:html', (str) => { | |
const bgtheme = hexo.theme.config.Mytheme; | |
return str.replace('</head>', ` | |
<script> | |
window.bgtheme = "${bgtheme}"; | |
</script> | |
</head>`); | |
}); |
endtabs
作用是在渲染 html 后,获取主题配置文件的参数 bgtheme
,并通过 window.bgtheme
传递到前端脚本。
randombg.js
的类似前面随机文章封面,但设置封面是通过 F12
获取网站对应封面元素,再进行设置,但注意,由于设置封面是使用了 url()
的形式,其中的图片链接参数的空格会被忽略,因此要加上空格转换为 %20
的代码 const backgroundUrl = backimg.replace(/ /g, "%20")
,此外,要想获取到封面元素,主题配置文件中的参数 background
必须要设置一个默认封面,网页才能渲染出元素用于脚本获取。(该脚本需要在主题配置文件进行 inject 注入,每次刷新网页都会进行更新)
# 随机磁贴封面背景
设置随机背景,使用的是前端能动态刷新的 js 脚本实现,并与后端 js 进行通信传递参数,在 \themes\butterfly\source\js
中新建 random_mag_bg.js
,此为前端脚本,负责刷新封面;在 \themes\butterfly\scripts
中新建 setmagtheme.js
,此为后端脚本,负责获取配置文件 ( _config.yml
) 参数,并传递到前端 js。
setmagtheme.js
的代码如下:
tabs setmagtheme, 2
hexo.extend.filter.register('after_render:html', (str) => { | |
const { config } = hexo; | |
// 读取选定主题 | |
const selectedTheme = config.selected_theme; | |
return str.replace('</head>', ` | |
<script> | |
window.selectedTheme = "${selectedTheme}"; | |
console.log("当前mag主题:", window.selectedTheme); | |
</script> | |
</head>`); | |
}); |
hexo.extend.filter.register('after_render:html', (str) => { | |
const selectedTheme = hexo.theme.config.Mytheme | |
return str.replace('</head>', ` | |
<script> | |
window.selectedTheme = "${selectedTheme}"; | |
console.log("当前mag主题:", window.selectedTheme); | |
</script> | |
</head>`); | |
}); |
endtabs
由此将配置文件的参数 config.selected_theme
通过 window.selectedTheme
传递到前端 js。
random_mag_bg.js
与 randobg.js
类似,也是获取网页对应部分元素设置背景图片,不过不需要在配置文件先配置 message.cover
,但同样需要在主题配置文件注入。
tip warning faa-horizontal animated-hover 有空时可以将配置文件的三个 theme 合为一个 endtip
note success simple 已成功统一参数为 Mytheme 2024.10.25 endnote
# 一些小坑
# 自动部署遇到问题
- 在
Github Actions
启动自动部署时,发现当按时间触发时,random_img.js
并没有按日期更换主题,而当push
触发时,却能切换,查找资料,发现原来是因为时间触发时没有清理图片缓存导致没法更新 ,解决方法就是在图片链接后加这样每次加载图片都会变化,但加上这个字符串并不会影响原来图片的有效性。'?v=' + new Date().getTime()
,例如https://cloudflare-imgbed-9os.pages.dev/file/1729429003335_kon_24.webp?v=1729578064697
。 - 在首次进行自动部署时,需要获取追番信息的话,需要在
autodeploy.yml
中加入相应代码:
- name: 生成静态文件 | |
run: | | |
hexo bangumi -u #或者hexo bangumi -u 'SESSDATA' | |
hexo clean | |
hexo generate |
-
10.25 更新:重新写一个自动部署程序,前面通过在图片后加日期字符串并不起作用,于是采用
hexo deploy
的方式进行部署。步骤如下:- 在生成 SSH 密钥时,确保生成 PEM 格式的密钥:
h ssh-keygen -t rsa -b 4096 -m PEM -C "your_email@example.com"
- 将 SSH 公钥添加到 GitHub:
- 打开 GitHub 网站,在你的用户设置中找到
Settings > SSH and GPG keys
- 点击
New SSH key
,将生成的id_ed25519.pub(假如是id_ed25519)
文件中的内容复制并粘贴到 GitHub 的 SSH 公钥输入框中。
- 打开 GitHub 网站,在你的用户设置中找到
- 在 GitHub Actions 中添加 SSH 私钥:
- 进入你的 GitHub 项目页面,点击
Settings > Secrets and variables > Actions
。 - 添加一个新的
Secret
,命名为ACTIONS_DEPLOY_KEY
,并将id_ed25519
文件的内容复制进去。注意,这里是 SSH 的私钥。
- 进入你的 GitHub 项目页面,点击
- 修改 _config.yml 使用 SSH URL:
- 使用 SSH URL 代替 HTTPS,修改 _config.yml 文件的 deploy 配置,如下所示:
l deploy:
type: git
repo: git@github.com:ei4869/ei4869.github.io.git
branch: main
- 使用 SSH URL 代替 HTTPS,修改 _config.yml 文件的 deploy 配置,如下所示:
- 更新 GitHub Actions 工作流以支持 SSH:
l name: 自动部署
on:
push:
branches:
- master
release:
types:
- published
schedule:
# 每天的 0 点和 3 点(北京时间)自动部署
- cron: '0 16 * * *' # UTC 时间 16 点对应北京时间 0 点.
- cron: '0 19 * * *' # UTC 时间 19 点对应北京时间 3 点.
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: 检查分支
uses: actions/checkout@v2
with:
ref: master
- name: 安装 Node
uses: actions/setup-node@v1
with:
node-version: "20.x"
- name: 设置时区
run: echo "TZ='Asia/Shanghai'" >> $GITHUB_ENV.
- name: 安装 Hexo
run: |
export TZ='Asia/Shanghai'
npm install hexo-cli -g
- name: 缓存 Hexo
uses: actions/cache@v1
id: cache
with:
path: node_modules
key: $<!--swig0-->-$<!--swig1-->
- name: 安装依赖
if: steps.cache.outputs.cache-hit != 'true'
run: |
npm install --save
- name: 生成静态文件
run: |
export TZ='Asia/Shanghai' # 设置时区
hexo clean
hexo generate
gulp
- name: 配置 Git 用户信息和分支
run: |
git config --global user.name "$"
git config --global user.email "$"
- name: 设置 SSH 密钥
uses: webfactory/ssh-agent@v0.5.3
with:
ssh-private-key: $<!--swig4-->
- name: 部署
run: |
hexo deploy
通过以上,能实现定时自动重启项目,并且随机文章封面能定时更新。
# hexo-butterfly-categories-card 插件 bug
该插件 bug 显示的分类的名字和描述对应不上,于是暂时没有其他方法,只能不设置 message.descr
参数,即不显示描述。
# 自定义一个樱花飘落脚本
原脚本樱花是全屏飘落,我在 gallery\index.md
中通过
<script async src="https://npm.elemecdn.com/tzy-blog/lib/js/other/sakura.js"></script> |
进行注入,但要想部分区域注入樱花特效的话,我新建了 js\sakuraa.js
,通过修改获取的网页的元素可进行指定区域内飘落。
# 相册界面魔改
本质通过外挂标签设置图库集合,在其 index.md
中添加:
<div class="gallery-group-main"> | |
galleryGroup name description link img-url | |
galleryGroup name description link img-url | |
galleryGroup name description link img-url | |
</div> |
但我为了指定单独修改 gallery
的界面,为其添加了指定的类 gallery-page
,如下:(10.25,更好的指定 class 的方法)
tabs gallery-page, 2
<body class="gallery-page"> | |
<div class="gallery-group-main"> | |
galleryGroup name description link img-url | |
galleryGroup name description link img-url | |
galleryGroup name description link img-url | |
</div> | |
</body> |
<body> | |
<div class="gallery-group-main"> | |
galleryGroup name description link img-url | |
galleryGroup name description link img-url | |
galleryGroup name description link img-url | |
</div> | |
<script> | |
document.addEventListener("DOMContentLoaded", function() { | |
document.body.classList.add('gallery-page'); | |
}); | |
</script> | |
</body> |
endtabs
这样该页面就有了一个独立的指明身份的 class。 span red, (使用 script 脚本注入,动态更改 body 的 class 为指定 class,不会被其他样式改变,保证 class 为想要的 class) 而后续要改动该页面样式,比如去除页面里的文本白框,让放置的图片融于背景,只需调节 css 样式:
/* 特定页面(如 gallery 页面)样式设置 */ | |
.gallery-page{ | |
background: transparent !important; | |
} | |
/* 设置单独相册背景 */ | |
.gallery-page #web_bg { | |
background: url(https://cloudflare-imgbed-9os.pages.dev/file/1729429000558_kon_23.webp) !important; | |
background-size: cover !important; | |
background-position: center center !important; | |
background-repeat: no-repeat !important; | |
} | |
.gallery-page .page #page-header { | |
background: transparent !important; | |
} | |
.gallery-page .page #content-inner #page { | |
background: transparent !important; | |
border: none !important; /* 去除边框 */ | |
backdrop-filter: none !important; | |
box-shadow: none !important; /* 去除阴影 */ | |
} | |
.gallery-page .page #footer::before, | |
.gallery-page .page #page-header::before { | |
background: initial !important; | |
} |
之后,要去除子图库的背景白框时,只需要在其 md 文件中,指定 class 为 gallery-page
即可,例如:
tabs gallery-page, 2
<body class="gallery-page"> | |
gallery | |
 | |
endgallery | |
</body> |
<body> | |
gallery | |
 | |
endgallery | |
<script> | |
document.addEventListener("DOMContentLoaded", function() { | |
document.body.classList.add('gallery-page'); // 将类名添加为 music-page | |
}); | |
</script> | |
</body> |
endtabs
还有个小坑,子图库界面一开始加载时,里面的图片会一直抖动,也就是高一直在微微变化,查找资料发现是因为图片样式没有固定,导致为了适应布局图片会自己一直在变,解决方法是在 css 中加入固定样式的代码:
/* 调节相册样式,防止抖动 */ | |
.gallery-items { | |
position: relative; | |
overflow: hidden; /* 防止内容溢出 */ | |
} | |
.item { | |
position: absolute; | |
width: 348px; /* 你可以根据需要调整 */ | |
height: 205px; /* 确保所有图片区域的大小一致 */ | |
margin: 0; /* 去掉默认外边距 */ | |
padding: 0; /* 去掉默认内边距 */ | |
} | |
.item a { | |
display: block; | |
width: 100%; | |
height: 100%; | |
} | |
.item img { | |
width: 100%; | |
height: 100%; | |
object-fit: cover; /* 确保图片保持比例并覆盖整个容器 */ | |
display: block; /* 去除图片底部的空白空间 */ | |
} | |
body.gallery-page { | |
margin: 0; | |
padding: 0; | |
overflow-x: hidden; /* 避免水平滚动 */ | |
} |
# 移动端背景图片样式改进
在手机端背景图片会只显示一部分,为了解决这个问题,在 css 中加入代码,使能容纳完整图片,虽然图片不会充满区域,但观感更好吧 (额额,其实 cover 的话也还行吧)。
/* 调节背景图片 */ | |
#web_bg { | |
background-size: cover; /* 确保背景图片覆盖整个容器 */ | |
background-position: center center; /* 将背景图片居中显示 */ | |
background-repeat: no-repeat; /* 防止背景图片重复 */ | |
height: 100vh; /* 将背景高度设置为视口高度 */ | |
width: 100vw; /* 将背景宽度设置为视口宽度 */ | |
overflow: hidden; /* 确保背景图片不会超出边界 */ | |
} | |
/* 针对移动端调整 */ | |
@media only screen and (max-width: 768px) { | |
#web_bg { | |
background-size: contain; /* 确保移动端背景图片按比例缩放 */ | |
} | |
} |
# Aplayer 播放器
音乐播放器魔改参考链接:魔改音乐播放器
# Aplayer 播放器魔改 (自改版本)
为了解决 anzhiyu 版本的 bug,只能自己重写一个界面,不过更简单,但解决了 bug。我的播放器用了官方的播放器样式。
- 主题配置文件引入 js:
bottom: | |
- <script src="https://cdn.jsdelivr.net/npm/meting@2/dist/Meting.min.js"></script> |
- 配置 music 的 md 文件
--- | |
title: 音乐馆 | |
date: 2021-04-24 21:41:30 | |
# type: music | |
aplayer: true | |
top_img: false | |
comments: false | |
aside: false | |
--- | |
<body class="music-page"> | |
meting "9224307215" "tencent" "playlist" "autoplay" "mutex:false" "listmaxheight:440px" "preload:none" "theme:#ad7a86" | |
<script> | |
document.addEventListener("DOMContentLoaded", function() { | |
document.body.classList.add('music-page'); // 将类名添加为 music-page | |
}); | |
</script> | |
<script> | |
// 获取 class 为 page 的第一个元素 | |
const pageElement = document.querySelector('.page'); | |
if (pageElement) { | |
// 查找其子元素中是否有 ID 为 page 的元素 | |
const childElement = pageElement.querySelector('#page'); | |
if (childElement) { | |
// 修改元素的 ID | |
childElement.id = 'music-page'; | |
} | |
} | |
</script> | |
<script> | |
document.addEventListener("DOMContentLoaded", function() { | |
// 获取需要调整的元素 | |
const contentInner = document.getElementById("content-inner"); | |
const musicPage = document.getElementById("music-page"); | |
const pageTitle = musicPage.querySelector(".page-title"); | |
if (pageTitle) { | |
// 在 content-inner 之后插入标题 | |
contentInner.insertAdjacentElement('beforebegin', pageTitle); | |
pageTitle.style.textAlign = 'center'; | |
pageTitle.style.marginTop = '0px'; // 可以根据需要调整 | |
} | |
}); | |
</script> | |
<canvas id="universe"></canvas> | |
<script defer src="/js/universe.js"></script> | |
</body> |
先不管后面的脚本注入,主要是 meting "9224307215" "tencent" "playlist" "autoplay" "mutex:false" "listmaxheight:440px" "preload:none" "theme:#ad7a86"
这里使用 meting
引入播放器, listmaxheight
是歌单列表长度, theme
是歌曲封面背景色 (不是歌单页面背景色)。
- 配置 music 页面特征 ID:
首先为了和其他页面区分开来,给界面一个独立的class
也就是music-page
,通过脚本注入:
<script> | |
document.addEventListener("DOMContentLoaded", function() { | |
document.body.classList.add('music-page'); // 将类名添加为 music-page | |
}); | |
</script> |
再给后面的 class:page
的 id:page
的子元素重命名为 id:music-page
:
<script> | |
// 获取 class 为 page 的第一个元素 | |
const pageElement = document.querySelector('.page'); | |
if (pageElement) { | |
// 查找其子元素中是否有 ID 为 page 的元素 | |
const childElement = pageElement.querySelector('#page'); | |
if (childElement) { | |
// 修改元素的 ID | |
childElement.id = 'music-page'; | |
} | |
} | |
</script> |
这样能方便指定 id
调整 css 样式。
- 调整 css
由于 css 代码比较多,所以直接新建一个mymusic.css
,后续再在主题配置文件注入即可。配置内容为:
/* 消除文本框,使用透明背景 */ | |
.page #music-page { | |
background: transparent !important; /* 设置背景透明 */ | |
border: none !important; /* 去除边框 */ | |
box-shadow: none !important; /* 去除阴影 */ | |
} | |
#article-container { | |
background-color: rgba(255, 255, 255, 0) !important; /* 透明背景 */ | |
border: 1px solid rgba(0, 0, 0, 0.1) !important; /* 可选:半透明边框 */ | |
margin-top: 80px; /* 调节整个歌单和顶部的距离 */ | |
} | |
/* 调节整个歌单的背景色,这里是淡灰色 */ | |
.aplayer { | |
/* opacity: 0.6; */ | |
background-color: rgba(235, 224, 224, 0.395) !important; | |
} | |
/* 固定整个页面,禁止垂直滚动,这里 z-index 设为 auto,防止因为 z-index 设置不合适导致进度条和音量按钮 bug*/ | |
#music-page { | |
position: fixed; /* 使其固定在屏幕上 */ | |
top: 0; /* 距离顶部 0 */ | |
left: 0; /* 距离左侧 0 */ | |
width: 100vw; /* 占满视口的宽度 */ | |
height: 100vh; /* 占满视口的高度 */ | |
overflow: hidden; /* 禁用内部滚动条 */ | |
z-index: auto; /* 确保在其他内容之上 */ | |
background-color: #ffffff; /* 可选:设置背景颜色 */ | |
} | |
/* 隐藏整个页面的水平滚动条 */ | |
body { | |
overflow-x: hidden; | |
} | |
/* 自设 music 页面单独背景,指定为 music-page 里的 web_bg*/ | |
.music-page #web_bg { | |
background: url(https://cloudflare-imgbed-9os.pages.dev/file/1729677618289_8b35b49fcc4e3a1c37c128f8c1eff16b558fb1bb.jpg@1256w_708h_!web-article-pic.webp) !important; | |
background-size: cover !important; | |
background-position: center center !important; | |
background-repeat: no-repeat !important; | |
} | |
/* 调整歌曲列表,每行的高度和字体大小,行变宽字体变大 */ | |
.aplayer .aplayer-list ol li{ | |
line-height: 45px !important; | |
font-size: 15px !important; | |
} | |
.aplayer.aplayer-withlrc .aplayer-info { | |
padding: 0 7px 0 !important; | |
margin-top: 0px; | |
} | |
.page #music-page { | |
margin-top: -10px; | |
} | |
/* 加粗歌曲标题作者歌词的文字 */ | |
.aplayer .aplayer-info .aplayer-music .aplayer-title, | |
.aplayer .aplayer-info .aplayer-music .aplayer-author, | |
.aplayer .aplayer-lrc p.aplayer-lrc-current { | |
font-weight: bold !important; /* 加粗文字 */ | |
color: #333 !important; | |
} | |
/* 加粗歌曲列表的标题作者索引的文字 */ | |
.aplayer .aplayer-list ol li .aplayer-list-title, | |
.aplayer .aplayer-list ol li .aplayer-list-author { | |
font-weight: bold !important; /* 加粗文字 */ | |
color: #333 !important; | |
} | |
.aplayer .aplayer-list ol li .aplayer-list-index { | |
font-weight: bold !important; /* 加粗索引 */ | |
color: #333 !important; | |
} | |
/* 加深显示播放时间颜色 */ | |
.aplayer .aplayer-info .aplayer-controller .aplayer-time .aplayer-time-inner{ | |
font-weight: bold !important; | |
color: #333 !important; | |
} | |
/* 加深显示图标颜色 */ | |
.aplayer .aplayer-info .aplayer-controller .aplayer-time .aplayer-icon svg{ | |
filter: brightness(0.2) !important; /* 降低填充亮度 */ | |
} | |
.aplayer .aplayer-info .aplayer-controller .aplayer-time .aplayer-icon svg path{ | |
stroke: #333 !important; /* 加深轮廓线条颜色 */ | |
} | |
/* 调整歌单列表,每一行的上下边框颜色使其变浅 */ | |
#article-container .aplayer ol li { | |
border: 1px solid rgba(232, 208, 208, 0.5) !important; /* 使用 RGBA 来设置边框颜色,使其变浅 */ | |
/* 你可以根据需要调整边框宽度和样式 */ | |
} | |
/* 调整歌单最左侧指示条的颜色 */ | |
.aplayer .aplayer-list ol li.aplayer-list-light .aplayer-list-cur { | |
background-color: #0a1de9 !important; /* 设置新的背景颜色 */ | |
} | |
/* 调整歌单列表当前播放曲目的背景高亮颜色 */ | |
.aplayer .aplayer-list ol li.aplayer-list-light { | |
background-color: #f2f5ea !important; | |
} | |
/* 隐藏版权说明 */ | |
#footer-wrap .copyright{ | |
display: none !important; | |
} | |
/* 隐藏模型 */ | |
.music-page #live2d-widget { | |
display: none !important; | |
} | |
/* 适用于移动端的媒体查询 */ | |
@media (max-width: 768px) { | |
/* 适配 #music-page */ | |
#music-page { | |
position: fixed; | |
top: 0; | |
left: 0; | |
width: 100vw; /* 占满视口宽度 */ | |
height: 100vh; /* 占满视口高度 */ | |
overflow-y: auto; /* 启用垂直滚动 */ | |
background-color: #ffffff; /* 可选:背景颜色 */ | |
padding: 10px; /* 为移动端增加内边距 */ | |
} | |
/* 适配标题,直接隐藏 */ | |
.music-page h1 { | |
display: none !important; | |
} | |
/* 适配 #article-container */ | |
#article-container { | |
background-color: rgba(255, 255, 255, 0) !important; | |
border: 1px solid rgba(0, 0, 0, 0.1) !important; | |
margin-top: 60px; | |
padding: 10px; /* 增加内边距,使内容更贴合移动端 */ | |
} | |
/* 适配 APlayer 音乐播放器 */ | |
.aplayer { | |
background-color: rgba(235, 224, 224, 0.5) !important; /* 半透明背景 */ | |
margin-bottom: 20px; | |
} | |
/* 调整播放列表的字体和间距 */ | |
.aplayer .aplayer-list ol li { | |
line-height: 40px !important; /* 调整行高 */ | |
font-size: 14px !important; /* 调整字体大小 */ | |
} | |
/* 调整歌词部分 */ | |
.aplayer .aplayer-info .aplayer-music .aplayer-title, | |
.aplayer .aplayer-info .aplayer-music .aplayer-author, | |
.aplayer .aplayer-lrc p.aplayer-lrc-current { | |
font-size: 14px !important; /* 调整歌词字体大小 */ | |
color: #333 !important; /* 设置字体颜色 */ | |
} | |
/* 调整播放时间的显示,更易读 */ | |
.aplayer .aplayer-info .aplayer-controller .aplayer-time .aplayer-time-inner { | |
font-weight: bold !important; | |
color: #333 !important; | |
font-size: 14px !important; /* 调整字体大小,适合移动设备 */ | |
} | |
/* 针对移动端:调节图标填充亮度 */ | |
.aplayer .aplayer-info .aplayer-controller .aplayer-time .aplayer-icon svg { | |
filter: brightness(0.3) !important; /* 略微减小亮度调节 */ | |
width: 18px !important; /* 调整图标大小,适合移动端 */ | |
height: 18px !important; /* 确保图标在移动端的可点击性 */ | |
} | |
/* 针对移动端:加深图标线条颜色 */ | |
.aplayer .aplayer-info .aplayer-controller .aplayer-time .aplayer-icon svg path { | |
stroke: #333 !important; | |
} | |
/* 播放器控制按钮适配 */ | |
.aplayer .aplayer-info { | |
padding: 0 10px !important; /* 调整内边距 */ | |
margin-top: 0px; | |
} | |
/* 播放列表项目的边框 */ | |
#article-container .aplayer ol li { | |
border: 1px solid rgba(232, 208, 208, 0.5) !important; | |
} | |
/* 设置播放列表项目的背景颜色 */ | |
.aplayer .aplayer-list ol li.aplayer-list-light { | |
background-color: #f2f5ea !important; | |
} | |
/* 隐藏版权信息 */ | |
#footer-wrap .copyright { | |
display: none !important; | |
} | |
/* 设置控制栏和播放列表之间的空隙 */ | |
.aplayer .aplayer-info { | |
margin-bottom: 10px; | |
} | |
} |
对于音乐界面标题的处理,直接在 md 文件注入 js,动态调整其位置,使其上升到 content-inner
级,居中加粗显示:
<script> | |
document.addEventListener("DOMContentLoaded", function() { | |
// 获取需要调整的元素 | |
const contentInner = document.getElementById("content-inner"); | |
const musicPage = document.getElementById("music-page"); | |
const pageTitle = musicPage.querySelector(".page-title"); | |
if (pageTitle) { | |
// 在 content-inner 之后插入标题 | |
contentInner.insertAdjacentElement('beforebegin', pageTitle); | |
pageTitle.style.textAlign = 'center'; | |
pageTitle.style.marginTop = '0px'; // 可以根据需要调整 | |
} | |
}); | |
</script> |
通过以上,PC 端和移动端的音乐界面都能正常显示,没有 bug 啦!你的名字夜晚飞星的蓝黑天空加上几乎透明浅灰的歌单列表,还是挺适配的。至此,自改的 Aplayer 播放器还算可以。
# 其它碎碎念 (10.25)
# 随机磁贴封面的 bug
昨天还是会出现偶尔磁贴封面图片为 null 的情况,明明图片链接都有效,明明使用了 IntersectionObserver
懒加载,而且再次刷新页面大概率就又正常了,今天重新改下代码,加入了获取随机图片时如果获取为 null 再次获取的代码,看起来稳定了很多,刷了 n 遍界面都没问题,但不知道还会不会出现,看后续表现吧,贴上改后代码: span red, 10.25 16:34: 呜呜,好像彻底解决了啊,原来是 addEventListener('DOMContentLoaded',);
的问题啊,改用 window.onload
而不是 DOMContentLoaded
,能确保所有资源和元素都已加载。贴上再次改进后的完整代码:
'use strict'; | |
// 在所有资源加载完成后执行脚本 | |
window.onload = function () { | |
// 定义主题图片对象 | |
const themes = { | |
kon: [ | |
"https://cloudflare-imgbed-9os.pages.dev/file/1729306198549_kon_5.webp", | |
"https://cloudflare-imgbed-9os.pages.dev/file/1729306191301_kon_7.webp", | |
"https://cloudflare-imgbed-9os.pages.dev/file/1729306191486_kon_6.webp", | |
"https://cloudflare-imgbed-9os.pages.dev/file/1729428993734_kon_18.webp", | |
"https://cloudflare-imgbed-9os.pages.dev/file/1729428993850_kon_19.webp", | |
"https://cloudflare-imgbed-9os.pages.dev/file/1729428996317_kon_20.webp", | |
"https://cloudflare-imgbed-9os.pages.dev/file/1729429001817_kon_21.webp", | |
"https://cloudflare-imgbed-9os.pages.dev/file/1729429002735_kon_22.webp", | |
"https://cloudflare-imgbed-9os.pages.dev/file/1729429000558_kon_23.webp", | |
"https://cloudflare-imgbed-9os.pages.dev/file/1729429003335_kon_24.webp", | |
"https://cloudflare-imgbed-9os.pages.dev/file/1729429007799_kon_25.webp", | |
"https://cloudflare-imgbed-9os.pages.dev/file/1729428998336_kon_26.webp", | |
"https://cloudflare-imgbed-9os.pages.dev/file/1729429009566_kon_27.webp", | |
"https://cloudflare-imgbed-9os.pages.dev/file/1729429003993_kon_28.webp", | |
"https://cloudflare-imgbed-9os.pages.dev/file/1729429003878_kon_29.webp", | |
"https://cloudflare-imgbed-9os.pages.dev/file/1729429010529_kon_30.webp", | |
"https://cloudflare-imgbed-9os.pages.dev/file/1729429007853_kon_31.webp", | |
"https://cloudflare-imgbed-9os.pages.dev/file/1729429008008_kon_32.webp", | |
"https://cloudflare-imgbed-9os.pages.dev/file/1729429010316_kon_33.webp", | |
"https://cloudflare-imgbed-9os.pages.dev/file/1729429013647_kon_15.webp", | |
"https://cloudflare-imgbed-9os.pages.dev/file/1729429006011_kon_16.webp", | |
"https://cloudflare-imgbed-9os.pages.dev/file/1729429018278_kon_17.webp" | |
], | |
sp: [ | |
"https://cloudflare-imgbed-9os.pages.dev/file/1729306222386_summer pockets_1.webp", | |
"https://cloudflare-imgbed-9os.pages.dev/file/1729306218357_summer pockets_12.webp", | |
"https://cloudflare-imgbed-9os.pages.dev/file/1729306217685_summer pockets_3.webp" | |
] | |
// 可以在此添加更多主题 | |
}; | |
// 获取随机图片的函数 | |
function getRandomCoverImage(theme) { | |
const themeImages = themes[theme]; | |
if (themeImages && themeImages.length > 0) { | |
let coverImage = null; | |
let attempt = 0; | |
const maxAttempts = 10; // 最大尝试次数 | |
while (!coverImage && attempt < maxAttempts) { | |
const randomIndex = Math.floor(Math.random() * themeImages.length); | |
coverImage = themeImages[randomIndex]; | |
attempt++; | |
if (!coverImage) { | |
console.warn("获取图片失败,重新尝试..."); | |
} | |
} | |
// 如果仍然没有有效图片,返回一个默认图片 | |
return coverImage || "https://cloudflare-imgbed-9os.pages.dev/file/1729429018278_kon_17.webp"; | |
} else { | |
console.warn("Theme not defined or no images available."); | |
return "https://cloudflare-imgbed-9os.pages.dev/file/1729429018278_kon_17.webp"; // 默认图片链接 | |
} | |
} | |
// 获取当天的主题 | |
function getDailyTheme() { | |
const today = new Date(); | |
const dayOfYear = Math.floor((today - new Date(today.getFullYear(), 0, 0)) / 86400000); | |
const themeNames = Object.keys(themes); | |
const themeIndex = dayOfYear % themeNames.length; | |
return themeNames[themeIndex]; | |
} | |
function updateCategoryBarCover() { | |
const theme = window.selectedTheme === '' ? getDailyTheme() : window.selectedTheme; | |
const categoryItems = document.querySelectorAll('.categoryBar-list-item'); | |
if (!categoryItems || categoryItems.length === 0) { | |
console.warn("未找到任何分类项元素,确保页面结构正确。"); | |
return; | |
} | |
console.log("当前磁贴主题:", theme); | |
console.log("选中的分类项数量:", categoryItems.length); | |
// 使用 IntersectionObserver 进行懒加载 | |
const observer = new IntersectionObserver((entries) => { | |
entries.forEach(entry => { | |
if (entry.isIntersecting) { | |
const item = entry.target; | |
const coverImage = getRandomCoverImage(theme).replace(/ /g, "%20"); | |
if (coverImage) { | |
item.style.backgroundImage = `url(${coverImage})`; | |
item.style.backgroundSize = "cover"; | |
item.style.backgroundRepeat = "no-repeat"; | |
item.style.backgroundPosition = "center center"; | |
console.log("已设置封面图片:", coverImage); | |
} else { | |
console.error("未能获取有效的封面图片"); | |
} | |
// 停止观察已加载的元素 | |
observer.unobserve(item); | |
} | |
}); | |
}); | |
categoryItems.forEach(item => { | |
observer.observe(item); | |
}); | |
} | |
// 执行更新操作 | |
updateCategoryBarCover(); | |
}; |
# 阅读进度按钮问题
参考链接,但实际使用有 bug,目前涉及的需要修改的文件的代码都已更新,解决了 bug。
# 夜间模式切换
参考链接。先按 1.0
操作再到 2.0
替换部分 1.0
内容才能实现。
# gulp 全局资源压缩
参考链接。但注意,要生成 \public
文件夹,需要使用 hexo generate
命令,而不能使用 hexo g
,真是离谱啊。
# 源码连接仓库
- 创建存放源码的私有仓库
创建仓库存放源码,设为私密。创建完成后,需要把博客的源码push
到这里。首先获取远程仓库地址,此处虽然 SSH 和 HTTPS 均可。SSH 在绑定过ssh key
的设备上无需再输入密码,HTTPS 则需要输入密码。 - 在 [Blogroot] 路径下
右键->Git Bash Here
这一步会在你的博客目录下新建一个h git init # 初始化 git
.git
文件夹。因为是隐藏文件夹,所以需要你先确保当前目录下隐藏文件夹可见才能看到它。 - 添加屏蔽项
在远端提交前,我们需要先调整一下屏蔽项,能够使用指令进行安装的内容不包括在需要提交的源码内,这样可以显著减少需要提交的文件量和加快提交速度。打开 [Blogroot]/.gitignore(也是隐藏文件), 输入以下内容:如果不是t .DS_Store
Thumbs.db
db.json
*.log
node_modules/
public/
.deploy*/
.deploy_git*/
.idea
themes/butterfly/.git
butterfly
主题,记得替换最后一行内容为你自己当前使用的主题。 - 第一次 push 到远程仓库
右键->Git Bash Here
:h git add . # 添加文件到本地仓库
git commit -m "自定义内容即可" # 添加文件描述信息
git remote add origin git@github.com:username/YourRepositoryName.git #链接远程仓库地址,创建主分支
- 偶尔会遇到一些与远端内容不一致的问题,一般是因为在创建远程仓库时点选了生成
README.md
或者license
的选项,输入指令:h # 要是提示 origin 已经存在,那么执行
git remote rm origin
# 然后再重新尝试
git remote add origin git@github.com:username/YourRepositoryName.git
git pull origin YourBranchName # 把远程仓库的新增的内容覆盖到本地仓库
git push -u origin YourBranchName -f
# 把本地仓库的文件推送到远程仓库的主分支,
#YourBranchName 记得替换成分支名,一般是 master。
#2020 年 10 月后 github 新建仓库默认分支改为 main
# -f 是强制提交,主要是因为前后版本不一致造成的。
# 然后执行以下指令生成网站并部署到 GitHub 上。
#(Hexo 部署网站是根据_config.yml 内的配置,所以不受影响)
hexo generate
hexo deploy
- 后续更新仓库
只需要在本地 bash 执行 git 三连即可推送代码改动到仓库,若添加了自动部署,则可自动在推送的同时更新网站。h git add .
git commit -m "..."
git push
# 将改动推送到 GitHub
# 小知识
\public
文件夹是网站展示的内容的文件夹,\source
则是存放数据的文件夹,包括发布的文章,页面的 md 文件等等。而配置网站主题样式之类的一般在\theme\butterfly
里面操作,可以添加js、css、img
以及其他比如pug
等文件吧。- 要改变页面的样式,若需要脚本注入,可在 md 文件里用
script
标签进行动态修改,其他简单的不需要用到函数什么的只需要修改样式,可以F12
查找要修改的网页元素,然后使用 css 进行修改,一般可以用一个通用的custom.css
在主题配置文件注入即可。 \theme\butterfly\script
里的 js 文件是后端文件,是静态的,需要重启项目才能执行,刷新网页并不会执行,不需要注入,会直接调用,也能直接读取配置文件的参数;\theme\butterfly\source\js
里的 js 文件是前端文件,是动态的,会随着网页刷新再次执行,需要在主题配置文件 inject,要获取到配置文件的参数,可以在\theme\butterfly\script
创建后端文件,通过window.参数
传递配置文件的参数,前端文件再通过window.参数
获取到参数。可以利用这一点读取参数进行一些动态刷新操作。- 一般本地资源的调用路径都是以
\theme\butterfly\source
为根路径吧,比如注入 js 时路径用\js\xxx.js
即可,引用图片时用\img\xxx.jpg
即可。 - 网页元素,在 css 中,一般是
.class
,#id
的方式。要想直接改变目标元素的样式,可以F12
检查,找到对应元素所在位置,一般双击它在下面栏的样式表会有它和其他元素的依赖关系,直接复制在 css 中使用即可。如图:
# 完善音乐界面 (11.16)
在音乐界面增加卡片,用于选择对应主题的歌单。具体实现为:
- 修改
music
文件夹里的index.md
文件内容,使用外挂标签设置链接卡片,修改后的文件内容为:
--- | |
title: 音乐馆 | |
# type: music | |
aplayer: true | |
top_img: false | |
comments: false | |
aside: false | |
--- | |
<body> | |
sitegroup | |
site KON, url=/music/kon, screenshot=https://cloudflare-imgbed-9os.pages.dev/file/1729429000558_kon_23.webp, description=轻音永不毕业! | |
site Summer Pockets, url=/music/sp, screenshot=https://cloudflare-imgbed-9os.pages.dev/file/1729919005838_summer pockets_3.webp, description=唯有那份眩目,未曾忘记... | |
site Eva, url=/music/eva, screenshot=https://cloudflare-imgbed-9os.pages.dev/file/1729915127264_EVA_5.webp, description=梦是现实的延续,现实是梦的终结。 | |
site Ghibli, url=/music/ghibli, screenshot=https://cloudflare-imgbed-9os.pages.dev/file/1730449515623_ghibli_22.webp, description=只要有想见的人,自己就不再是孤单一人。 | |
site love, url=/music/love, screenshot=https://cloudflare-imgbed-9os.pages.dev/file/1729765205778_1729764735768.webp, description=心灵补给站。 | |
endsitegroup | |
<script> | |
document.addEventListener("DOMContentLoaded", function() { | |
document.body.classList.add('musiccard-page'); | |
}); | |
</script> | |
</body> |
其中,为该页面设置了 class 为 "musiccard-page",用于调整该页面的 css 样式。
- 设置该页面的 css 样式如下:
.site-card .img { | |
height: 200px !important; /* 设置高度 */ | |
overflow: hidden !important; | |
} | |
.site-card .img img { | |
object-fit: cover !important; /* 图片适应容器 */ | |
width: 100% !important; | |
height: 100% !important; | |
} | |
.info .title { | |
font-size: 1.2rem !important; /* 设置标题字体大小 */ | |
font-weight: bold !important; /* 加粗标题字体 */ | |
color: rgb(18, 188, 240) !important; /* 使标题字体颜色更加醒目,采用鲜艳颜色 */ | |
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5) !important; /* 为标题添加阴影效果,增强对比 */ | |
} | |
.info .desc { | |
font-size: 1.2rem !important; /* 设置描述字体大小 */ | |
font-weight: 500 !important; /* 为描述设置较轻的粗细 */ | |
color: #fff !important; /* 白色字体 */ | |
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.3) !important; /* 轻微阴影增强可读性 */ | |
} | |
.musiccard-page .page #content-inner #page #article-container { | |
border: none !important; /* 移除边框 */ | |
box-shadow: none !important; /* 移除阴影效果 */ | |
} | |
/* 特定页面(如 gallery 页面)样式设置 */ | |
.musiccard-page{ | |
background: transparent !important; | |
} | |
.musiccard-page #web_bg { | |
filter: blur(5px) !important; /* 添加模糊效果,8px 是模糊的强度 */ | |
} | |
.musiccard-page #web_bg::after { | |
content: ''; | |
position: absolute; | |
top: 0; | |
left: 0; | |
right: 0; | |
bottom: 0; | |
background: rgba(0, 0, 0, 0.3); /* 调整背景透明度,0.5 为 50% 透明度 */ | |
z-index: 1; /* 使透明覆盖层位于背景图上方 */ | |
} | |
.musiccard-page .page #page-header { | |
background: transparent !important; | |
} | |
.musiccard-page .page #content-inner #page { | |
background: transparent !important; | |
border: none !important; /* 去除边框 */ | |
backdrop-filter: none !important; | |
box-shadow: none !important; /* 去除阴影 */ | |
} | |
.musiccard-page .page #footer::before, | |
.musiccard-page .page #page-header::before { | |
background: initial !important; | |
} |
主要就是去除背景,使边框透明等,还有就是对背景进行适当模糊和透明度处理,去除页脚等。并对每个卡片图片的大小,以及标题描述的文字进行适当处理,使更加醒目。
- 在
music
文件夹新建存储主题歌单的page
界面,这里包括kon
、sp
等,这些页面里的index.md
沿用原本音乐界面格式,歌单 id 不同,这样就形成了不同卡片主题有着不同歌单。
# 修改 bug (11.23)
- 发现在博客里的公式渲染后出现问题,例如 的 '_' 会被识别为强调文本的作用,实际应表示下标。查找资料后解决如下:最终还是使用已经安装的
hexo-renderer-kramed
,但需要先执行:然后主题配置文件里开启 mathjax 支持,enable 置为 true。之后在h npm uninstall hexo-renderer-marked
博客目录\node_modules\kramed\lib\rules\inline.js
中做如下变动:原先的正则表达式会识别_和 $ 并用于强调文本,修改后_不会被识别,此后 $ $ 的行内表达式正常渲染。n // em: /^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
em: /^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
但要进行自动部署,由于是自动重新安装依赖项,所以需要在自动部署代码加入自动修改 inline.js 内容的脚本。于是在博客根目录创建fix_kramed.js
,内容为:原本采用正则表达式匹配原规则再用新规则替换,但一直匹配不到,最后采用字符串替换的方法成功替换了 em 规则。`autodeploy.yml 增加内容:t const fs = require('fs');
const path = require('path');
const inlineRulesPath = path.join(
__dirname,
'node_modules',
'kramed',
'lib',
'rules',
'inline.js'
);
fs.readFile(inlineRulesPath, 'utf8', (err, data) => {
if (err) {
console.error('Failed to read inline.js:', err);
process.exit(1);
}
// 原有的 em 规则字符串
const originalEmRuleStr = "em: /^\\b_((?:__|[\\s\\S])+?)_\\b|^\\*((?:\\*\\*|[\\s\\S])+?)\\*(?!\\*)/";
// 新的 em 规则字符串
const newEmRuleStr = "em: /^\\*((?:\\*\\*|[\\s\\S])+?)\\*(?!\\*)/";
// 查找原有的 em 规则并替换
const index = data.indexOf(originalEmRuleStr);
if (index !== -1) {
// 替换原有的 em 规则
const updatedData = data.substring(0, index) + newEmRuleStr + data.substring(index + originalEmRuleStr.length);
fs.writeFile(inlineRulesPath, updatedData, 'utf8', (err) => {
if (err) {
console.error('Failed to update inline.js:', err);
process.exit(1);
}
console.log('Successfully updated Kramed rules.');
console.log('Updated Rule:', newEmRuleStr);
});
} else {
console.log('Original em rule not found.');
}
});
注意,调试时,可在自动部署代码中加入:l - name: 安装依赖
if: steps.cache.outputs.cache-hit != 'true'
run: |
npm install --save
- name: 修改 Kramed 规则
run: node fix_kramed.js
- name: 生成静态文件
用于检查l - name: Debug File Path
run: ls node_modules/kramed/lib/rules
- name: Output Kramed Rules for Debugging
run: cat node_modules/kramed/lib/rules/inline.js
inline.js
路径和文件内容,检查是否成功替换。这些操作后,规则修改,自动部署后也能正常渲染行内公式了。 - 文章里 pdf 显示问题解决方法:安装
hexo-pdf
:可以在存放静态资源的h npm install --save hexo-pdf
source
文件夹里新建pdf
文件夹用于存放 pdf 资源,在文章里,要显示 pdf 时,使用命令:注意文件名不要含特殊字符。n pdf /pdf/xxx.pdf
- 音乐播放界面的歌单发现 bug,歌单底部歌曲鼠标点击不触发,减小歌单列表长度能解决一点,但后面发现是底部 footer 元素阻挡,原先只是隐藏但仍存在会影响点击,于是使用脚本自动删除 footer 后解决,在每个音乐界面的 md 文件后加入:之后歌单所有歌曲点击正常。
n <script>
document.addEventListener('DOMContentLoaded', () => {
const footer = document.getElementById('footer');
if (footer) {
footer.remove(); // 删除 footer 元素
}
});
</script>
# 优化看板娘 (12.09)
原来的看板娘不能随时关闭,而且比较单调,于是在这里进行参考,重新设置了看板娘样式。具体步骤为:
- Fork 原项目,并在本地
git clone
fork 的项目,为了保持代码清晰和便于回退,保留原分支,创建新分支:将h git clone https://github.com/yourusername/repository-name.git
cd repository-name
git checkout -b new-branch-name
new-branch-name
替换为要新建的分支名。 - 在本地进行代码修改,然后推送到新分支:
h git add .;git commit -m "update on 24.12.08";git push origin customize
customize
为示例分支。 - 由于仓库的资源使用 jsdelivr CDN 加载,而 jsdelivr 的缓存机制会导致修改的内容无法及时更新,折腾半天,采用不断打新标签的方式更新代码内容。当有新的代码改动提交时,创建新标签并推送,然后只需要更改链接即可。每次修改代码后,使用上述命令推送内容到仓库,并创建新标签和推送内容。
h git add .;git commit -m "update on 24.12.08";git push origin customize;git tag -a v1.0.6 -m "更新代码";git push origin v1.0.6
相应地,修改autoload.js
的路径链接:t //live2d_path 参数建议使用绝对路径
const live2d_path = "https://fastly.jsdelivr.net/gh/ei4869/live2d-widget-fork@v1.0.6/";
ei4869
和live2d-widget-fork
分别为用户名和仓库,新的标签@v1.0.6
能刷新缓存,同步更新 CDN 内容。
要想删除某个 tag 时,采用以下命令:要想删除除了某个 tag (如 v1.0.6) 外的其他 tag 时,采用以下命令:h git tag -d v1.0.0;git push origin --delete v1.0.0
h git tag | grep -v 'v1.0.6' | xargs git tag -d;
git ls-remote --tags origin | awk '{print $2}' | grep -v 'v1.0.6' | sed 's|refs/tags/||' | xargs -I {} git push origin --delete {}
- 自定义看板娘样式,可以修改
live2d-widget-fork
里的以下内容:waifu.css
用于修改具体网页里呈现的样式,我这里修改了原来的大小 (#live2d),位置 (#waifu),文字框高度 (#waifu-tips) 等,最主要的autoload.js
用来设置主函数,可以修改里面的代码:我这里把功能按钮 (t initWidget({
waifuPath: live2d_path + "waifu-tips.json",
//apiPath: "https://live2d.fghrsh.net/api/",
cdnPath: "https://fastly.jsdelivr.net/gh/fghrsh/live2d_api/",
tools: ["hitokoto", "switch-model", "switch-texture", "photo", "quit"]
});
tools
) 减少了两个 (纸飞机游戏和模型信息)。通过修改apiPath
或cdnPath
里的资源可以增添喜欢的模型,这里还没深入了解 (这两个只需配置一个即可)。另外waifu-tips.json
中定义了触发条件(selector,CSS 选择器)和触发时显示的文字(text)可以根据需要修改 (主要就是改变一些动作触发的对话),而src/waifu-tips.js
包含了按钮和对话框的逻辑,可以根据代码一步步分析进行个性化配置 (还没深入并修改)。目前就只改了 tools 和 css 里的配置。