hexo的fluid主题添加相册功能及自定义页面
本文最后更新于:8 个月前
在阅读本博客之前,我默认你已经配置好你的hexo博客。 如还未配置请参考hexo配置文档:https://hexo.bootcss.com ,我的博客主题是fluid,fluid用户参考手册:https://hexo.fluid-dev.com/docs
创建相册页面
新建相册页 hexo new page photos,编辑 /source/photos/index.md,输入以下内容:
1 |
|
Github+picgo搭建图床
我的相册是采用GitHub+jsDelivr加速来加载图片,这样有利于更快加载图片,当然你可以选择跳过这一步,将你的图片放到你的博客中。或者搭建其他图床。
下载picgo
百度搜索picgo下载picgo
picgo下载网址:https://molunerfinn.com/PicGo/
创建github仓库
创建一个公共的仓库,用来存放你的图片。
在picgo中设置图床
在picgo中选择github图床,如果你的图床仓库为其他的,请依据的你选择。以下是github图床设置
仓库名选择你创建的仓库,分支名为main,存储路径按照你相册文件名存放。设置自定义域名,我的域名中加入了cdn.jsdelivr这个会加速我们的图片加载速度。token设置在你创建的github仓库中点击setting找到personal access token将创建好的token复制进token设置中
至此我们的图床设置完毕,点击上传图片之后,图片就可以保存到githu仓库中,在picgo中选择相册,即可查看图片链接来进行访问
处理图片json文件
这一步是为了将相册所有的图片信息目录及大小保存到json文件中,访问通过固定域名+json文件中的图片路径即可访问
在blog目录下创建相册文件
创建imagescreate文件夹,结构如下图所示:
创建phototool.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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82 const fs = require('fs-extra');
const path = require('path');
const imageSize = require('image-size');
const rootPath="imagescreate/" //相册相对路径
class PhotoExtension {
constructor() {
this.size = 64;
this.offset = [0, 0];
}
}
class Photo {
constructor() {
this.dirName = '';
this.fileName = '';
this.iconID = '';
this.extension = new PhotoExtension();
}
}
class PhotoGroup {
constructor() {
this.name = '';
this.children = [];
}
}
function createPlotIconsData() {
let allPlots = [];
let allPlotGroups = [];
const plotJsonFile = path.join(__dirname, './photosInfo.json');
const plotGroupJsonFile = path.join(__dirname, './photos.json');
if (fs.existsSync(plotJsonFile)) {
allPlots = JSON.parse(fs.readFileSync(plotJsonFile));
}
if (fs.existsSync(plotGroupJsonFile)) {
allPlotGroups = JSON.parse(fs.readFileSync(plotGroupJsonFile));
}
fs.readdirSync(__dirname).forEach(function(dirName) {
const stats = fs.statSync(path.join(__dirname, dirName));
const isDir = stats.isDirectory();
if (isDir) {
const subfiles = fs.readdirSync(path.join(__dirname, dirName));
subfiles.forEach(function(subfileName) {
// 如果已经存在 则不再处理
// if (allPlots.find(o => o.fileName === subfileName && o.dirName === dirName)) {
// return;
// }
// 新增标
const plot = new Photo();
plot.dirName = dirName;
plot.fileName = subfileName;
const imageInfo = imageSize(rootPath+dirName + "/" + subfileName);
plot.iconID = imageInfo.width + '.' + imageInfo.height + ' ' + subfileName;
allPlots.push(plot);
console.log(`RD: createPlotIconsData -> new plot`, plot);
// 为新增标添加分组 暂时以它所处的文件夹为分组
let group = allPlotGroups.find(o => o.name === dirName);
if (!group) {
group = new PhotoGroup();
group.name = dirName;
allPlotGroups.push(group);
console.log(`RD: createPlotIconsData -> new group`, group);
}
group.children.push(plot.iconID);
});
}
});
fs.writeJSONSync(plotJsonFile, allPlots);
fs.writeJSONSync(plotGroupJsonFile, allPlotGroups);
}
createPlotIconsData();
生成json文件
- 运行npm i -S image-size 导入获取文件大小第三方包
- 运行node imagescreate/phototool.js生成json文件
找到photos.json,将其复制到source/photos目录下。内容示例: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[
{
"name": "美食",
"children": [
"1036.584 foot1.jpg",
"1036.584 foot1.jpg",
"3000.4000 IMG20190906183445.jpg",
"4000.3000 IMG20210306173452.jpg",
"4000.3000 IMG20210624124705.jpg"
]
},
{
"name": "风景",
"children": [
"1036.584 foot1.jpg",
"1036.584 foot1.jpg",
"3000.4000 IMG20190906183445.jpg"
]
}
{
"name": "生活",
"children": [
"2401.1600 1619402831098.jpeg",
"1440.1080 1637328153132.jpeg",
"1440.1080 1637581717468.jpeg"
]
}
]编写相册js文件
在 /source/js/ 目录下创建 photoWall.js:然后使用注册器将需要的js,css注入,在scripts/injector.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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147var imgDataPath = "/photos/photos.json"; //图片名称高宽信息json文件路径 //填入你的路径,注意修改
var imgPath = "http://imghe.xyz/"; //图片访问路径 //填入你的路径,注意修改
var imgMaxNum = 50; //图片显示数量
var windowWidth =
window.innerWidth ||
document.documentElement.clientWidth ||
document.body.clientWidth;
if (windowWidth < 768) {
var imageWidth = 145; //图片显示宽度(手机端)
} else {
var imageWidth = 250; //图片显示宽度
}
const photo = {
page: 1,
offset: imgMaxNum,
init: function () {
var that = this;
$.getJSON(imgDataPath, function (data) {
that.render(that.page, data);
//that.scroll(data);
that.eventListen(data);
});
},
constructHtml(options) {
const {
imageWidth,
imageX,
imageY,
name,
imgPath,
imgName,
imgNameWithPattern,
} = options;
const htmlEle = `<div class="card lozad" style="width:${imageWidth}px">
<div class="ImageInCard" style="height:${
(imageWidth * imageY) / imageX
}px">
<a data-fancybox="gallery" href="${imgPath}${name}/${imgNameWithPattern}"
data-caption="${imgName}" title="${imgName}">
<img class="lazyload" data-src="${imgPath}${name}/${imgNameWithPattern}"
src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="
onload="lzld(this)"
lazyload="auto">
</a>
</div>
</div>`;
return htmlEle;
},
render: function (page, data = []) {
this.data = data;
if (!data.length) return;
var html,
imgNameWithPattern,
imgName,
imageSize,
imageX,
imageY,
li = "";
let liHtml = "";
let contentHtml = "";
data.forEach((item, index) => {
const activeClass = index === 0 ? "active" : "";
liHtml += `<li class="nav-item" role="presentation">
<a class="nav-link ${activeClass} photo-tab" id="home-tab" photo-uuid="${item.name}" data-toggle="tab" href="#${item.name}" role="tab" aria-controls="${item.name}" aria-selected="true">${item.name}</a>
</li>`;
});
const [initData = {}] = data;
const { children = [],name } = initData;
children.forEach((item, index) => {
imgNameWithPattern = item.split(" ")[1];
imgName = imgNameWithPattern.split(".")[0];
imageSize = item.split(" ")[0];
imageX = imageSize.split(".")[0];
imageY = imageSize.split(".")[1];
let imgOptions = {
imageWidth,
imageX,
imageY,
name,
imgName,
imgPath,
imgNameWithPattern,
};
li += this.constructHtml(imgOptions);
});
contentHtml += ` <div class="tab-pane fade show active" role="tabpanel" aria-labelledby="home-tab">${li}</div>`;
const ulHtml = `<ul class="nav nav-tabs" id="myTab" role="tablist">${liHtml}</ul>`;
const tabContent = `<div class="tab-content" id="myTabContent">${contentHtml}</div>`;
$("#imageTab").append(ulHtml);
$(".ImageGrid").append(tabContent);
this.minigrid();
},
eventListen: function (data) {
let self = this;
var html,
imgNameWithPattern,
imgName,
imageSize,
imageX,
imageY,
li = "";
$('a[data-toggle="tab"]').on("shown.bs.tab", function (e) {
$(".ImageGrid").empty();
const selectId = $(e.target).attr("photo-uuid");
const selectedData = data.find((data) => data.name === selectId) || {};
const { children,name } = selectedData;
let li = "";
children.forEach((item, index) => {
imgNameWithPattern = item.split(" ")[1];
imgName = imgNameWithPattern.split(".")[0];
imageSize = item.split(" ")[0];
imageX = imageSize.split(".")[0];
imageY = imageSize.split(".")[1];
let imgOptions = {
imageWidth,
imageX,
imageY,
name,
imgName,
imgPath,
imgNameWithPattern,
};
li += self.constructHtml(imgOptions);
});
$(".ImageGrid").append(li);
self.minigrid();
});
},
minigrid: function () {
var grid = new Minigrid({
container: ".ImageGrid",
item: ".card",
gutter: 12,
});
grid.mount();
$(window).resize(function () {
grid.mount();
});
},
};
photo.init();至此博客相册功能已经完成1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19const js = hexo.extend.helper.get('js').bind(hexo);
const css = hexo.extend.helper.get('css').bind(hexo);
hexo.extend.injector.register('head_end', () => {
return css('https://cdn.staticfile.org/fancybox/3.5.7/jquery.fancybox.min.css');
}, 'photo');
hexo.extend.injector.register('head_end', () => {
return js('https://cdn.jsdelivr.net/npm/jquery@3/dist/');
}, 'photo');
hexo.extend.injector.register('head_end', () => {
return js('https://cdn.bootcdn.net/ajax/libs/lazyloadjs/3.2.2/lazyload.js');
}, 'photo');
hexo.extend.injector.register('head_end', () => {
return js('https://cdn.jsdelivr.net/npm/minigrid@3.1.1/dist/minigrid.min.js');
}, 'photo');
hexo.extend.injector.register('body_end', () => {
return js('/js/photoWall.js');
},"photo");
页面自定义
hexo框架基本具备了博客搭建的基本功能,通常情况我们修改配置就可以了,但是为了使页面更美观,我们通常情况下会自定义页面,你可以自己编写css、js等,通过主题配置引入,具体方法参见主题文档。也可以使用注入器来自定义页面,参考文档:https://hexo.io/zh-cn/api/injector.html
本博客所有文章除特别声明外,如需转载或引用,请注明出处!