Appearance
主要思路:
(1)利用node+ali-oss读取阿里云bucket信息
(2)hexo页面请求数据进行渲染
hexo操作
引入文件
在自定义help.js文件内添加如下代码,并利用Inject插入到hexo中
javascript
/*
* @Description:
* @Date: 2023-05-18 16:28:45
* @LastEditTime: 2023-05-18 19:41:55
*/
/* 阿里云相册流自定义函数 起点 */
function waterfall(a) {
function b(a, b) {
var c = window.getComputedStyle(b);
return parseFloat(c["margin" + a]) || 0;
}
function c(a) {
return a + "px";
}
function d(a) {
return parseFloat(a.style.top);
}
function e(a) {
return parseFloat(a.style.left);
}
function f(a) {
return a.clientWidth;
}
function g(a) {
return a.clientHeight;
}
function h(a) {
return d(a) + g(a) + b("Bottom", a);
}
function i(a) {
return e(a) + f(a) + b("Right", a);
}
function j(a) {
a = a.sort(function (a, b) {
return h(a) === h(b) ? e(b) - e(a) : h(b) - h(a);
});
}
function k(b) {
f(a) != t &&
(b.target.removeEventListener(b.type, arguments.callee), waterfall(a));
}
"string" == typeof a && (a = document.querySelector(a));
var l = [].map.call(a.children, function (a) {
return (a.style.position = "absolute"), a;
});
a.style.position = "relative";
var m = [];
l.length &&
((l[0].style.top = "0px"),
(l[0].style.left = c(b("Left", l[0]))),
m.push(l[0]));
for (var n = 1; n < l.length; n++) {
var o = l[n - 1],
p = l[n],
q = i(o) + f(p) <= f(a);
if (!q) break;
(p.style.top = o.style.top),
(p.style.left = c(i(o) + b("Left", p))),
m.push(p);
}
for (; n < l.length; n++) {
j(m);
var p = l[n],
r = m.pop();
(p.style.top = c(h(r) + b("Top", p))), (p.style.left = c(e(r))), m.push(p);
}
j(m);
var s = m[0];
a.style.height = c(h(s) + b("Bottom", s));
var t = f(a);
window.addEventListener
? window.addEventListener("resize", k)
: (document.body.onresize = k);
}
// imgStatus 判断图片是否加载进来了
!(function () {
(this.loaded = 0),
(this.failed = 0),
(this.total = 0),
(this.watch = function (a, b) {
var c = document.querySelectorAll(a);
if (!c.length)
return console.log(
"[imgStatus]: There aren't any images associated with this selector (" +
a +
")!"
);
this.total = c.length;
for (var d = 0; d < this.total; d++)
isCached(c[d].src)
? this._setLoaded(b)
: c[d].addEventListener
? (c[d].addEventListener("load", this._setLoaded.bind(this, b)),
c[d].addEventListener("error", this._setFailed.bind(this, b)))
: (c[d].attachEvent("onload", this._setLoaded.bind(this, b)),
c[d].attachEvent("onerror", this._setFailed.bind(this, b)));
}),
(this.isCached = function (a) {
var b = new Image();
return (b.src = a), b.complete;
}),
(this._setFailed = function (a, b) {
++this.failed, "function" == typeof a && a(this);
}),
(this._setLoaded = function (a, b) {
++this.loaded, "function" == typeof a && a(this);
}),
(this.isDone = function () {
return this.loaded + this.failed === this.total ? !0 : !1;
}),
"object" == typeof window && (window.imgStatus = this);
})();
// https://tokinx.github.io/lately/ 判断距今时间
!(function () {
window.Lately = new (function () {
var t = this;
this.lang = {
second: "秒",
minute: "分钟",
hour: "小时",
day: "天",
month: "个月",
year: "年",
ago: "前",
error: "NaN",
};
var e = function (e) {
e = new Date(n(e));
var r = new (function () {
(this.second = (Date.now() - e.getTime()) / 1e3),
(this.minute = this.second / 60),
(this.hour = this.minute / 60),
(this.day = this.hour / 24),
(this.month = this.day / 30),
(this.year = this.month / 12);
})(),
i = Object.keys(r)
.reverse()
.find(function (t) {
return r[t] >= 1;
});
return (
(i
? (function (t, e) {
return Math.floor(t) + e;
})(r[i], t.lang[i])
: t.lang.error) + t.lang.ago
);
},
n = function (t) {
return (
(t = new Date(
t &&
("number" == typeof t
? t
: t.replace(/-/g, "/").replace("T", " "))
)),
!isNaN(t.getTime()) && t.getTime()
);
};
return {
init: function () {
var r =
arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {},
i = r.target,
a = void 0 === i ? "time" : i,
o = r.lang;
o && (t.lang = o);
var u = !0,
h = !1,
l = void 0;
try {
for (
var s, c = document.querySelectorAll(a)[Symbol.iterator]();
!(u = (s = c.next()).done);
u = !0
) {
var f = s.value,
g = n(f.dateTime) || n(f.title) || n(f.innerHTML) || 0;
if (!g) return;
(f.title = new Date(g).toLocaleString()), (f.innerHTML = e(g));
}
} catch (t) {
(h = !0), (l = t);
} finally {
try {
!u && c.return && c.return();
} finally {
if (h) throw l;
}
}
},
format: e,
};
})();
})();
/* 阿里云相册流自定义函数 终点 */页面内代码
新建相册页面hexo new page lifePhotos,粘贴如下代码
markdown
---
title: 我的生活
date: 2022-06-28 21:15:13
aside: false
---
<div class="gallery-photos page">
</div>
<style>
#article-container a img {margin: 0; border-radius:0;}
.gallery-photos{width:100%;margin-top: 10px;}
.gallery-photo{min-height:5rem;width:24.97%;padding:4px;position: relative;}
.gallery-photo a{border-radius:8px;display:block;overflow: hidden;}
.gallery-photo img{display: block;width:100%;animation: fadeIn 1s;cursor: pointer;transition: all .4s ease-in-out !important;}
.gallery-photo span.photo-title,.gallery-photo span.photo-time{max-width: calc(100% - 7px);line-height:1.8;position:absolute;left:4px;font-size:14px;background: rgba(0, 0, 0, 0.3);padding:0px 8px;color: #fff;animation: fadeIn 1s;}
.gallery-photo span.photo-title{bottom:4px;border-radius: 0 8px 0 8px;}
.gallery-photo span.photo-time{top:4px;border-radius: 8px 0 8px 0;}
.gallery-photo:hover img{transform: scale(1.1);}
@media screen and (max-width: 1100px) {.gallery-photo{width:33.3%;}}
@media screen and (max-width: 768px) {
.gallery-photo{width:49.9%;padding:3px}
.gallery-photo span.photo-time{display:none}
.gallery-photo span.photo-title{font-size:12px}
.gallery-photo span.photo-title{left:3px;bottom:3px;}
}
@keyframes fadeIn{0% {opacity: 0;}100%{opacity: 1;}}
.layout{
max-width:90% !important;
}
</style>自定义js
自定义js插入如下内容
javascript
// 适配pjax
function whenDOMReady() {
if (location.pathname == "/lifePhotos/") photos();
}
whenDOMReady();
document.addEventListener("pjax:complete", whenDOMReady);
// 自适应
window.onresize = () => {
if (location.pathname == "/lifePhotos/") waterfall(".gallery-photos");
};
// 函数
function photos() {
fetch("http://139.224.188.129:4545/")
.then((res) => res.json())
.then((data) => {
// // 记得修改memos地址
let html = "";
data.forEach((item) => {
let img = item.url,
title = item.title || ''
time = item.time.substr(0,4) + '-' + item.time.substr(4,2) + '-' + item.time.substr(6,2) || '';
html += `<div class="gallery-photo"><a href="${img}" data-fancybox="gallery" class="fancybox" data-thumb="${img}"><img class="photo-img" loading='lazy' decoding="async" src="${img}"></a>`;
title ? (html += `<span class="photo-title">${title}</span>`) : "";
time ? (html += `<span class="photo-time">${time}</span>`) : "";
html += `</div>`;
});
document.querySelector(".gallery-photos.page").innerHTML = html;
imgStatus.watch(".photo-img", () => {
waterfall(".gallery-photos");
});
window.Lately && Lately.init({ target: ".photo-time" });
})
.catch();
}后端操作
生成express文件
yaml
npm i express-generator -g -save
cd #到相应目录
express -e "瀑布流相册"
cd "瀑布流相册"
npm i安装阿里云和跨域库
yaml
npm i ali-oss cors --save使用app.use(cors)允许跨域请求
读取阿里云bucket相册列表
在routes/index.js中修改如下代码:
javascript
var express = require('express');
var router = express.Router();
let OSS = require('ali-oss');
/* GET home page. */
router.get('/', function(req, res, next) {
let client = new OSS({
// yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
region: 'oss-cn-hangzhou',
// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。
accessKeyId: 'LTAI5tSnEj7ZKnBqLJVNaHTf',
accessKeySecret: 'pE46MOV90fKnZkbd0Yp4OooK1JImFY',
bucket: 'jyh-img'
});
client.listV2({
prefix:'life/', //相册位置
'max-keys': 1000 //限制个数
}).then(dataList => {
dataList.objects.shift()
let photoList = []
dataList.objects.forEach(item => {
let time = item.name.split('life/')[1].split('.jpg')[0].split('-')[0]
let title = item.name.split('life/')[1].split('.jpg')[0].split('-')[1]
let url = item.url
photoList.push({time,title,url})
})
res.send(photoList.reverse())
}).catch(err => {
res.send(err)
})
});
module.exports = router;