碎碎念
最近广泛交友,在和朋友klcdm的聊天中,了解到了他按照洪哥的教程添加了一个分类条,于是我想要,在和星港的聊天中,了解到他又有改了加载动画,而我的加载动画还是可怜的原版动画,于是心动的我又想要了,再在和朋友们讨论的过程中,xing提到了,本站地址也会被识别成外链,所以我将三个板块都进行了魔改,最终也达到了比较好的效果,其中参考了其他大佬的想法,我也会将地址附在下面。
内容概述
- 洪哥的分类条无法动态添加分类,只能通过手动添加,我将其进行了改进,参考了hexo-theme-solitude主题,最终实现了自动添加分类组别。
- 外链卡片基于洪哥的教程,可以识别是否为本站地址,并显示不同的文字,并且支持自定义不同地址对应的图标。
魔改教程
注意:由于本次魔改修改了主题内部文件,一定要注意提前备份!一定要注意提前备份!一定要注意提前备份!如果没有魔改基础建议紧跟教程,如果有任何问题可以在下方评论区提出。
分类条
我原有的分类是店长的分类卡片,但总感觉占用空间有点大,且如果分类超过三个会显示滚动条。我在网站设计中尽量避免显示滚动条,因为感觉不够美观。为了使网站更加简洁,我决定按照朋友 klcdm 的推荐,使用洪哥的分类条。然而,洪哥的分类条是纯静态的,分类需要手动添加上去,明显不符合我的懒蛋需求。因此,我决定修改洪哥的分类条,并从 hexo-theme-solitude
中提取出动态分类条的功能,以便更简洁地显示所有分类并快捷切换。
效果展示
以下是分类条的展示效果,具体效果可以在首页自行感受。
亮色模式暗色模式
为了美观,我把横向分类的滚动条移除了,但是仍然可以移动,如果是手机的话,通过左右滑动即可拉动滚动条,但是不太明显,有需要的可以自行添加其他元素。
教程
新建文件[BlogRoot]themesbutterflylayoutincludescategoryBar.pug
文件,写入:
.category-bar-items#category-bar-items(class=is_home() ? 'home' : '')
.category-bar-item(class=is_home() ? 'select' : '', id="category-bar-home")
a(href=url_for('/'))= __('博客首页')
each item in site.categories.find({ parent: { $exists: false } }).data
.category-bar-item(class=select ? (select === item.name ? 'select' : '') : '', id=item.name)
a(href=url_for(item.path))= item.name
.category-bar-item
a(href=url_for('/archives/'))= __('文章存档')
div.category-bar-right
a.category-bar-more(href=url_for('/categories/'))= __('更多分类')
以上就是该滚动条的结构,下面我们开始实现样式的定义,新建文件[BlogRoot]themesbutterflysourcecss_layoutcategory-bar.styl
写入以下文件:
#category-bar
padding 7px 11px
background var(--card-bg)
border-radius 8px
display flex
white-space nowrap
overflow hidden
transition 0.3s
height 50px
width 100%
justify-content space-between
user-select none
align-items center
margin-bottom 20px
.category-bar-right
display flex
border-radius 8px
align-items center
.category-bar-more
margin-left 4px
margin-right 4px
font-weight 700
border-radius 8px
padding 0 8px
.category-bar-items
width 100%
white-space nowrap
overflow-x scroll
scrollbar-width: none
-ms-overflow-style: none
overflow-y hidden
display flex
border-radius 8px
align-items center
height 30px
&::-webkit-scrollbar
display: none
.category-bar-item
a
padding .1rem .5rem
margin-right 6px
font-weight 700
border-radius 8px
display flex
align-items center
height 30px
&.select
a
background #3eb8be
color var(--btn-color)
在pug文件中,所有的颜色我都尽量使用了butterfly主题自带的变量进行了替代,确保大部分人可以正常显示。
然后将其添加到不同的位置,比如我这里实现了添加到分类页面等位置,配合上pjax可以做到无刷更新,效果很好,打开文件[BlogRoot]themesbutterflylayoutcategory.pug
,添加其中两行代码,去掉加号即为正常缩进:
extends includes/layout.pug
block content
if theme.category_ui == 'index'
include ./includes/mixins/post-ui.pug
#recent-posts.recent-posts.category_ui
#category-bar.category-bar
include includes/categoryBar.pug
postUI
include includes/pagination.pug
else
include ./includes/mixins/article-sort.pug
#category
<div id="categories-chart" data-parent="true" style="height: 300px; padding: 10px;"></div>
.article-sort-title= _p('page.category') ' - ' page.category
articleSort(page.posts)
include includes/pagination.pug
注意上方的修改,需要将配置文件中,分类页面的主题改成index,否则不会显示。
下面我们将其添加到主页,打开文件[BlogRoot]themesbutterflylayoutindex.pug
文件,添加下面两行:
extends includes/layout.pug
block content
include ./includes/mixins/post-ui.pug
#recent-posts.recent-posts
#category-bar.category-bar
include includes/categoryBar.pug
postUI
include includes/pagination.pug
然后就是实现点击切换后,高亮部分跟随分类页面走的部分,为了和主题融合我还是修改源码,打开[BlogRoot]themesbutterflysourcejsmain.js
,添加js函数,比如我添加到了778行左右,switchComments
函数的上面:
/**
* 自己写的,实现功能切换类别表
*/
const setCategoryBarActive = () => {
const categoryBar = document.querySelector("#category-bar");
const currentPath = decodeURIComponent(window.location.pathname);
const isHomePage = currentPath === GLOBAL_CONFIG.root;
if (categoryBar) {
const categoryItems = categoryBar.querySelectorAll(".category-bar-item");
categoryItems.forEach(item => item.classList.remove("select"));
const activeItemId = isHomePage ? "category-bar-home" : currentPath.split("/").slice(-2, -1)[0];
const activeItem = document.getElementById(activeItemId);
if (activeItem) {
activeItem.classList.add("select");
}
}
};
然后再在引用部分执行这个函数,在同一个文件,找到下面的函数并添加函数的调用,位置看下方注释:
代码语言:javascript复制window.refreshFn = function () {
initAdjust()
if (GLOBAL_CONFIG_SITE.isPost) {
GLOBAL_CONFIG.noticeOutdate !== undefined && addPostOutdateNotice()
GLOBAL_CONFIG.relativeDate.post && relativeDate(document.querySelectorAll('#post-meta time'))
} else {
GLOBAL_CONFIG.relativeDate.homepage && relativeDate(document.querySelectorAll('#recent-posts time'))
GLOBAL_CONFIG.runtime && addRuntime()
addLastPushDate()
toggleCardCategory()
setCategoryBarActive() // 自己加的,用于切换类别栏目
}
最后,hexo三件套,应该就能看到效果了!请根据自己的需要进行定制化。
外链卡片
这个刚开始是从洪哥那里借(chao)鉴(xi)过来的,洪哥采用的方式是通过api获取头像,这样的好处就是头像一直会变动,但是缺点就是,如果头像大小过小,可能会导致显示效果不好,比如模糊等情况出现,为了美观,我刚开始将其全部改成了同样的头像,后面不满足了,想要将我自己的站点独立出来,于是就添加了根据域名判断并采用不同头像的做法,再就是Xing提出了,本站地址依然显示为“站外地址,请注意安全性”,于是就有了这个开端。
效果展示
站内地址暗色模式githubgitee
以上效果仅供部分展示,如果想要查看更多请自行测试,本文章中即有展示效果。
教程
新建文件[BlogRoot]themesbutterflyscriptstaglink.js
,写入以下内容:
function link(args) {
args = args.join(' ').split(',');
let title = args[0];
let sitename = args[1];
let link = args[2];
// 定义不同域名对应的头像URL
const avatarUrls = {
'github.com': 'https://cdn.qyliu.top/i/2024/07/27/66a461a3098aa.webp',
'csdn.net': 'https://cdn.qyliu.top/i/2024/07/27/66a461b627dc2.webp',
'gitee.com': 'https://cdn.qyliu.top/i/2024/07/27/66a461c3dea80.webp',
'zhihu.com': 'https://cdn.qyliu.top/i/2024/07/27/66a461cc20eb4.webp',
'stackoverflow.com': 'https://cdn.qyliu.top/i/2024/07/27/66a461d3be02e.webp',
'wikipedia.org': 'https://cdn.qyliu.top/i/2024/07/27/66a461db48579.webp',
'baidu.com': 'https://cdn.qyliu.top/i/2024/07/27/66a461e1ae5b5.webp',
'qyliu.top': 'https://cdn.qyliu.top/i/2024/08/01/66aae601dbc9b.webp',
'liushen.fun': 'https://cdn.qyliu.top/i/2024/08/01/66aae601dbc9b.webp',
'lius.me': 'https://cdn.qyliu.top/i/2024/08/01/66aae601dbc9b.webp',
};
// 定义白名单域名
const whitelistDomains = [
'lius.me', 'qyliu.top', 'liushen.fun'
];
// 获取URL的根域名
function getRootDomain(url) {
const hostname = new URL(url).hostname;
const domainParts = hostname.split('.').reverse();
if (domainParts.length > 1) {
return domainParts[1] '.' domainParts[0];
}
return hostname;
}
// 根据URL获取对应的头像URL
function getAvatarUrl(url) {
const rootDomain = getRootDomain(url);
for (const domain in avatarUrls) {
if (domain.endsWith(rootDomain)) {
return avatarUrls[domain];
}
}
return 'https://cdn.qyliu.top/i/2024/07/27/66a4632bbf06e.webp'; // 默认头像URL
}
// 检查是否在白名单中
function isWhitelisted(url) {
const rootDomain = getRootDomain(url);
for (const domain of whitelistDomains) {
if (rootDomain.endsWith(domain)) {
return true;
}
}
return false;
}
// 获取对应的头像URL
let imgUrl = getAvatarUrl(link);
// 判断并生成提示信息
// 判断并生成提示信息
let tipMessage = isWhitelisted(link)
? "✅来自本站,本站可确保其安全性,请放心点击跳转"
: "