Hexo-自定义样式

Hexo-自定义样式

网站使用 Hexo-NexT 主题:

0. NexT主题自定义

NexT 主题提供了使用数据文件来自定义默认样式的能力,可以避免侵入修改源码,相关设置在 NexT 主题配置文件内:

1
2
3
4
5
6
7
8
9
10
11
custom_file_path:
head: source/_data/NextStyle/layout/head.njk
header: source/_data/NextStyle/layout/header.njk
sidebar: source/_data/NextStyle/layout/sidebar.njk
postMeta: source/_data/NextStyle/post/post-meta.njk
postBodyEnd: source/_data/NextStyle/post/post-body-end.njk
footer: source/_data/NextStyle/layout/footer.njk
bodyEnd: source/_data/NextStyle/layout/body-end.njk
variable: source/_data/NextStyle/variables.styl
# mixin: source/_data/NextStyle/mixins.styl
style: source/_data/NextStyle/custom.styl

并且 NexT 内置了多种文章内的特殊格式:Tag Plugins

1. 侧栏头像动画

使用自定义头像,将图片放入 /source/images/ 下,然后在主题配置文件中修改:

1
2
3
4
5
6
7
8
9
avatar:
# 修改为自定义的头像图片文件路径,也可以是网络路径
url: /images/avatar.jpg
# 是否显示为圆形头像
rounded: true
# 头像透明度
opacity: 1
# 是否在鼠标覆盖在头像上时旋转头像
rotated: true

1.1 自定义头像旋转效果

头像的样式是通过 CSS 控制的,所以可以通过注入 custom.style 来修改。

1.1.1 鼠标Hover时旋转

如果想让鼠标一过去头像就控记不住记几鬼畜疯狂旋转,则在 custom.style 中添加自定义 CSS 动画:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
if hexo-config('avatar.rotated') {
.site-author-image {
transition: transform 1.0s ease-out;
}
/* 原本只是简单地逆时针旋转 180°
.site-author-image:hover {
transform: rotateZ(-180deg);
}
*/
// 鼠标 Hover 时执行 rotateAvatar 动画,动画每次 0.15 秒,线性加速度,重复无限次
.site-author-image:hover {
animation: rotateAvatar 0.15s linear infinite;
}
// rotateAvatar 定义动画为旋转 360 度
@keyframes rotateAvatar{from{transform: rotate(0deg)}
to{transform: rotate(360deg)}
}
}

鼠标覆盖头像鬼畜式旋转

1.1.2 唱片式旋转

如果想让头像一直缓慢旋转,不受其他操作影响,同样在 custom.style 中添加自定义 CSS 动画:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
if hexo-config('avatar.rotated') {
.site-author-image {
transition: transform 1.0s ease-out;
// 对自定义头像的 CSS 执行动画 rotateAvatar,动画每次 5 秒,线性加速度,重复无限次
animation: rotateAvatar 5s linear infinite;
}

// 去掉原本定义的鼠标 Hover 动画
.site-author-image:hover {
transform: none;
// animation: rotateAvatar 0.15s linear infinite;
}

// rotateAvatar 定义动画为从 0 度旋转岛 360 度
@keyframes rotateAvatar {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
}

唱片式旋转


2. 浏览器标签页动态标题

浏览器标签页动态标题

由于只在打开某篇文章时才需要这个动画效果,因此可以在自定义数据文件 post-body-end.njk 中加载一个 JS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
{# 可写进 js 文件中并放在【hexo/source/xxx/】目录下或【next/source/xxx/】目录下 #}
{# 然后通过:<script type="text/javascript" src="/xxx/*.js"></script> 方式调用 #}
{# 但目录不能以下划线开头(会视为隐藏文件夹而无法访问) #}
<script>
<!--动态浏览器标签-->
var OriginTitle = document.title;
var titleTime;
var titleTime2;
var titleTime3;
var blankTitle = "\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u3000"
blankTitle = blankTitle + blankTitle + blankTitle;
document.addEventListener('visibilitychange', function () {
if (document.hidden) {
$('[rel="icon"]').attr('href', "/images/favicon-32x32-next.png");
// 失去焦点时不切换标题
// document.title = "Waiting...";
document.title = OriginTitle;
clearTimeout(titleTime);
clearTimeout(titleTime2);
clearTimeout(titleTime3);
}
else {
document.title = "Welcome";
titleTime = setTimeout(function () {
document.title = "Back";
titleTime2 = setTimeout(function () {
document.title = "Welcome Back !";
titleTime3 = setTimeout(function () {
document.title = OriginTitle;
}, 500);
}, 300);
}, 300);
}
});
</script>

具体的文件名和路径请按照实际情况修改。其实这种三个定时器的嵌套比较 Low,不知道有没有办法可以重用定时器。

icon 处可以自定义一个小图像,可以是本地图像也可以是网络图片。不过需要注意的是,这里如果选择本地图片,“/”表示的就不是博客根目录而是主题根目录,所以 /images/ 其实等价于 /next/images/。同理,在主题配置文件中的 favicon 选项设置的也是浏览器标签页小图标,指定的路径也是以主题根目录为起始路径的。


3. 页码导航栏增加显示数量

默认情况下,Next 的页码导航栏只会显示以下页码,而其他页码将被隐藏:

  • 首页和尾页;
  • 当前页;
  • 当前页的前一页(如果有)和后一页(如果有);

例如:

1
2
3
4
5
6
7
8
// 当前选中第 1 页时:
[1] 2 ... 8

// 当前选中第 2 页时:
1 [2] 3 ... 8

// 当前选中第 6 页时:
1 ... 5 [6] 7 8

但总页数较少时,会导致中间页码很容易被隐藏,切换页面时很麻烦,因此可以修改配置增加可显示范围:

  • Next-8.0.0 及之后版本的配置文件在 Next/layout/_partials/pagination.njk,并在该文件中通过引用 Next/scripts/helpers/next-paginator.js 实现;

    1
    2
    3
    4
    5
    6
    7
    8
    hexo.extend.helper.register('next_paginator', function() {
    ......
    let paginator = this.paginator({
    ......
    mid_size : 1,
    });
    ......
    });
  • Next-8.0.0 之前版本的配置文件在 Next/layout/_partials/pagination.swig

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    {%- if page.prev or page.next %}
    <nav class="pagination">
    {{
    paginator({
    ......
    mid_size : 1,
    })
    }}
    </nav>
    {%- endif %}

其中 mid_size 即表示显示「当前页的前 mid_size 个页码」和「当前页的后 mid_size 个页码」,增大该值即可。


4. 自动更新站点发布时间

由于 Hexo 一般使用静态发布,网站更新后如果浏览器有本地缓存可能不会立即刷新,为了更好的判断网站版本,可以在发布 Hexo 时在控制台输出当前时间、并自动将该时间显示在网站中。实现该效果需要满足以下条件:

  • 可以感知 Hexo 的发布流程并执行自定义代码;
  • 可以将时间记录在某个 Hexo 定义的公共元素中,而与使用的主题 Theme 无关;
  • 不侵入主题 Theme 的代码,防止 切换/更新 主题时需要重新配置;

经过查找,网站的 titlesubtitle 均可满足,由于 title 通常需要作为品牌标识,最终选择使用 subtitle 来记录发布时间。

(1)将发布时间作为 subtitle 的默认值

编辑 Site/node_modules/hexo/lib/hexo/default_config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// 直接给 Date 类添加原型方法 format(),用于解析传入的格式。
// chalk 用于控制台彩色日志
const chalk = require('chalk');
Date.prototype.format = function(format) {
var o = {
"M+" : this.getMonth()+1, //月份
"d+" : this.getDate(), //日
"h+" : this.getHours(), //小时
"m+" : this.getMinutes(), //分
"s+" : this.getSeconds(), //秒
"q+" : Math.floor((this.getMonth()+3)/3), //季度
"S" : this.getMilliseconds() //毫秒
};
if(/(y+)/.test(format)) {
format=format.replace(RegExp.$1, (this.getFullYear()+"").substr(4 - RegExp.$1.length));
}
for(var k in o) {
if(new RegExp("("+ k +")").test(format)){
format = format.replace(RegExp.$1, (RegExp.$1.length==1) ? (o[k]) : (("00"+ o[k]).substr((""+ o[k]).length)));
}
}
// 输出生成时间(直接指定样式):\x1b 表示 ESC 的 ASCII 码,[40;92m 表示黑色背景绿色字体,末尾需要再加上 \x1b[0m 表示复原
// console.info(`\x1b[40;92m[Generation Time] >>> ${format}\x1b[0m`);
// 输出生成时间(通过 chalk 设置前景和背景),需要先引入:const chalk = require('chalk');
console.log(chalk`{rgb(11, 237, 183).bold.bgRgb(216, 72, 13) [Generation Time] >>> ${format}}`)
return format;
}

module.exports = {
// 把 SubTitle 定义为显示时间,但该文件定义的默认值仅在 _config.yml 中没有声明时生效。
subtitle: new Date().format("yyyy/MM/dd - hh:mm:ss"),
......
};

(2)删除 Hexo 网站配置中的 subtitle 字段,使其读取默认值

编辑 Site/_config.yml

1
2
title: XXX
# subtitle: # 删除或注释该字段,则 Hexo 会读取默认值

(3)根据主题显示时间

大部份主题(例如 Next)会直接读取 Hexo 定义的 subtitle 字段值并显示,无需额外适配。


其他收录