Hexo+NexT+腾讯对象存储COS实现相册(妹子卷轴)功能

前言

相簿功能一直是个人博客的强需求,但hexo/next到目前都没有支持相册功能。原因可能是图片存储对于静态博客而言不太方便,而动态的相册需要后台支持。最近发现了一篇博客,给hexo静态博客添加动态相册功能,利用腾讯云cos存储图片,获取cos的图片列表,然后展示成相册。刚好我的博客放在cos上,也想做一个相册(妹子图),就开干咯!

最终效果,传送门

hexo/next 动态相册开发流程

腾讯云cos存图片与配置

注册腾讯云

腾讯云注册过程略过。

使用cos

找到对象存储cos

使用cos

创建存储桶

配置存储桶

设置公有读私有写

配置跨域访问

删除Policy权限

ps:如果不删除Policy权限,会遇到403

上传图片

下载客户端工具

上传图片,直接拖动图片到存储桶

ps:由于后面代码的问题,需要在存储桶内创建文件夹,然后将图片放在文件夹内。不能存在图片和文件夹同级的情况。

hexo配置

创建page

创建一个page,示例取名为photo,执行hexo new page photo命令。

编辑index.md文件

编辑source\photo目录下的index.md文件,添加以下代码

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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
<style type="text/css">
/* 去除顶部距离 */
.main-inner{
margin-top: unset;
}

.box{
visibility: visible;
overflow: auto;
}

.box li{
float: left;
width: 25%;
position: relative;
overflow: hidden;
text-align: center;
list-style: none;
margin: 0;
display: inline;
padding: 0;
height: 250px;
}

.imgbox{
width: 100%;
overflow: hidden;
height: 250px;
}

img.imgitem{
padding: unset;
padding: unset;
border: unset;
position: relative;
padding: 0px;
height: 100%;
width: 100%;
object-fit: cover;
}

.title{
text-align: center;
font-size: 26px;
position: relative;
overflow-wrap: break-word;
font-family: 'Lato', "PingFang SC", "Microsoft YaHei", sans-serif;
padding: 0px !important;
margin: 0px !important;
}

/* 除去图片边框颜色 */
.posts-expand .post-body img{
padding: 0px !important;
border: 1px solid transparent;
}
.posts-expand .post-title {
display: none;
}

/* 加载更多的容器 */
.btn-more-posts{
text-align: center;
border: unset;
height: 100px;
width: 100%;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}

/* 加载更多框 */
.btn-more-posts span {
border: 1px solid #000;
border-radius: 5px;
padding: 10px 20px 10px 20px;
}

@media (max-width: 767px){
.box li {
width: 100%;
}

.box span {
min-height: 80px;
border-right: unset;
font-size: 17px;
}
.box p{
border-right: unset;
font-size: 12px;

}
.posts-expand {
margin: unset;
}
div#comments.comments.v {
width: 96%;
padding-top: 50px;
}

}

@media (min-width: 1600px){
.container .main-inner{
width: 100%;
}
}

</style>

<div id="box" class="box">
<h2 class="title" itemprop="name headline">妹子卷轴</h2>
</div>

<script type="text/javascript">

function loadXMLDoc(xmlUrl)
{
try //Internet Explorer
{
xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
}
catch(e)
{
try //Firefox, Mozilla, Opera, etc.
{
xmlDoc=document.implementation.createDocument("","",null);
}
catch(e) {
alert(e.message)
}
}

try
{
xmlDoc.async=false;
xmlDoc.load(xmlUrl);
}
catch(e) {
try //Google Chrome
{
var chromeXml = new XMLHttpRequest();
chromeXml.open("GET", xmlUrl, false);
chromeXml.send(null);
xmlDoc = chromeXml.responseXML.documentElement;
//alert(xmlDoc.childNodes[0].nodeName);
//return xmlDoc;
}
catch(e)
{
alert(e.message)
}
}
return xmlDoc;
}

//存储桶的访问域名(基础配置-访问域名)
var xmllink="https://todo.myqcloud.com"

xmlDoc=loadXMLDoc(xmllink);
var urls=xmlDoc.getElementsByTagName('Key');
var date=xmlDoc.getElementsByTagName('LastModified');
var wid=250;
var showNum=12; //每个相册一次展示多少照片
if ((window.innerWidth)>1200) {wid=(window.innerWidth*3)/18;}
var box=document.getElementById('box');
var i=0;

var content=new Array();
var tmp=0;
var kkk=-1;
for (var t = 0; t < urls.length ; t++) {
var bucket=urls[t].innerHTML;
var length=bucket.indexOf('/');
if(length===bucket.length-1){
kkk++;
content[kkk]=new Array();
content[kkk][0]={'url':bucket,'date':date[t].innerHTML.substring(0,10)};
tmp=1;
}
else {
content[kkk][tmp++]={'url':bucket.substring(length+1),'date':date[t].innerHTML.substring(0,10)};
}
}

for (var i = 0; i < content.length; i++) {
var conBox=document.createElement("div");
conBox.id='conBox'+i;
box.appendChild(conBox);
var title=content[i][0].url;
for (var j = 1; j < content[i].length && j < showNum+1; j++) {
var con=content[i][j].url;
var item=document.createElement("li");
item.innerHTML="<div class=imgbox id=imgbox style=height:"+wid+"px;><img class=imgitem src="+xmllink+'/'+title+con+" alt="+con+"></div>";
conBox.appendChild(item);
}
if(content[i].length > showNum){
var moreItem=document.createElement("button");
moreItem.className="btn-more-posts";
moreItem.id="more"+i;
moreItem.value=showNum+1;
let cur=i;
moreItem.onclick= function (){
moreClick(this,cur,content[cur],content[cur][0].url);
}
moreItem.innerHTML="<span style=display:inline;>加载更多</span>";
conBox.appendChild(moreItem);
}
}

function moreClick(obj,cur,cont,title){
var parent=obj.parentNode;
parent.removeChild(obj);
var j=obj.value;
var begin=j;
for ( ; j < cont.length && j < Number(showNum) + Number(begin); j++) {
console.log( Number(showNum) + Number(begin));
var con=cont[j].url;
var item=document.createElement("li");
item.innerHTML="<div class=imgbox id=imgbox style=height:"+wid+"px;><img class=imgitem src="+xmllink+'/'+title+con+" alt="+con+"></div>";
parent.appendChild(item);
}
if(cont.length > j){
obj.value=j;
parent.appendChild(obj);
}
}

</script>

修改代码中的xmllink,替换为存储桶访问域名。

测试预览

本地执行命令hexo s –debug时,图片会无法显示,需要在存储桶的配置中添加localhost,如图

部署上线

1
2
3
hexo clean
hexo g
hexo d

效果图

代码解析/样式改造

这个相册改了一下兰州小红鸡的相册样式,因为感觉有点浮夸,比较喜欢素一点的样式。本人前端渣渣,所以还是费了一些时间。在兰州小红鸡的博客下面问了一些问题,不过自己也是解决了。下面就简单介绍一下。

代码分为三部分,css、html、JavaScript。
css部分:除了新增一些样式外,还需要覆盖hexo主题的部分样式。如何覆盖可以使用chrome的开发者工具查看。
html部分:主要是一个box容器,另外还加了一个标题。
JavaScript:三个部分,loadXMLDoc方法获取cos存储桶的图片数据列表、调用loadXMLDoc之后的两个循环解析数据和渲染首页、moreClick渲染更多的图片。

1
2
3
4
5
6
7
8
9
10
11
12
13
// css部分
<style type="text/css">
...
</style>

// html部分
<div id="box" class="box">
<h2 class="title" itemprop="name headline">妹子卷轴</h2>
</div>

// JavaScript部分
<script type="text/javascript">
</script>

需要更改图片item样式,添加图片名称、上传时间,可以修改以下代码段。

1
item.innerHTML="<div class=imgbox id=imgbox style=height:"+wid+"px;><img class=imgitem src="+xmllink+'/'+title+con+" alt="+con+"></div>";

例如兰州小红鸡的博客,innerHTML中包含一个图片div、一个图片名称span、一个上传日期p。

1
item.innerHTML="<div class=imgbox id=imgbox style=height:"+wid+"px;><img class=imgitem src="+xmllink+'/'+bucket+" ></div><span>"+bucket+"</span><p>"+date[i].innerHTML.substring(0,10)+"</p>";

以上,欢迎交流哦:)