准备图片资源

将精挑细选的图片存放在支持外链的图床

部署随机图片 API(Vercel)

使用的开源项目

该项目支持:

  • 不同分类 随机返回图片
  • 每个分类对应一个独立 API 路径

项目目录结构

img_api/
├─ api/ # API 相关文件
│ ├─ data/ # 文本数据文件
│ │ ├─ background.txt
│ │ └─ cover.txt
│ ├─ data.json # JSON 数据文件
│ └─ randomImage.js # 随机图片接口逻辑

├─ public/ # 静态资源
│ ├─ favicon.ico
│ └─ index.html

├─ tool/ # 图片链接列表创建工具
│ └─ build_file_list.exe

├─ .gitignore
├─ build-data.js # 构建数据脚本
├─ node-dev.js # 本地测试脚本
├─ package.json
├─ package-lock.json
├─ README.md
├─ LICENSE
└─ vercel.json # 部署配置

添加或删除图片分类

图片分类通过 api/data 目录下的 .txt 文件 来控制:

  • 一个 .txt 文件 = 一个图片分类
  • 文件名即 API 路径

例如:https://your-domain.vercel.app/dongman

自定义图片链接

在对应的 .txt 文件中填写图片直链即可,例如 dongman.txt

1
2
3
https://example.com/dongman1.jpg
https://example.com/dongman2.jpg
...

项目提供了快速创建工具(Windows),在tool文件夹里

双击程序后,根据窗口提示操作即可完成

部署到 Vercel

  1. 新建一个 GitHub 仓库,上传修改后的项目
  2. 在 Vercel 中选择该仓库进行部署
  3. 部署完成后获得一个 Vercel 域名(该域名国内需要科学上网才能访问, 如果想直接访问需要绑定国内的域名)

访问效果:

  • /:项目主页
  • /random:随机返回一张图片
  • /分类名:随机返回该分类的一张图片

修改项目主页的内容

这个与 api 的使用没有关系, 但是最好还是让项目主页显示的内容与自己设定的图片类型同步

根据自己设定的类型, 修改public文件夹index.html文件中相应的内容就可以

千万不要忘了, 将修改后的项目文件重新提交到 GitHub 仓库里(Vercel 会自动重新部署, 所以不用担心)

将 API 应用到 Butterfly 主题

[blogroot]\_config.butterfly.yml中添加刚刚部署好的 api

例如, 我想让文章的封面使用 api 加载

1
2
3
4
5
6
7
8
9
10
11
cover:
# display the cover or not (是否顯示文章封面)
index_enable: true
aside_enable: true
archives_enable: true
# the position of cover in home page (封面顯示的位置)
# left/right/both
position: left
# When cover is not set, the default cover is displayed (當沒有設置cover時,默認的封面顯示)
default_cover:
- https://your-domain.vercel.app/类型

此时效果是:

  • 刷新页面会加载不同的图片
  • 但所有文章封面显示的是同一张图片

解决封面图片重复的问题(关键)

问题原因:Hexo 在生成页面时会 缓存同一个图片 URL,即使 API 是随机的,也只会请求一次。

解决方法:给图片 URL 增加随机参数

[blogroot]\themes\butterfly\scripts下, 新建random_cover.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
/**
* Butterfly
* random cover
*/

'use strict'

hexo.extend.filter.register('before_post_render', function (data) {
const { config } = this
if (config.post_asset_folder) {
const imgTestReg = /\.(png|jpe?g|gif|svg|webp)(\?.*)?$/
const topImg = data.top_img
const cover = data.cover
if (topImg && topImg.indexOf('/') === -1 && imgTestReg.test(topImg)) data.top_img = data.path + topImg
if (cover && cover.indexOf('/') === -1) data.cover = data.path + cover
}

if (data.cover === false) {
data.randomcover = randomCover()
return data
}

data.cover = data.cover || randomCover()
return data
}, 0)

const crypto = require('crypto')

function randomCover() {
const theme = hexo.theme.config
let cover
let num

if (theme.cover && theme.cover.default_cover) {
if (!Array.isArray(theme.cover.default_cover)) {
cover = theme.cover.default_cover
} else {
num = Math.floor(Math.random() * theme.cover.default_cover.length)
cover = theme.cover.default_cover[num]
}
} else {
cover = theme.default_top_img
}
if (theme.cover.suffix == 1) {
cover = cover + "?" + crypto.randomUUID()
}
return cover
}

[blogroot]\_config.butterfly.yml中添加变量suffix

1
2
3
4
5
6
7
8
9
10
11
12
13
14
cover:
# display the cover or not (是否顯示文章封面)
index_enable: true
aside_enable: true
archives_enable: true
# the position of cover in home page (封面顯示的位置)
# left/right/both
position: left
# 在api链接上添加的后缀(用于使用图片api时,让每个文章的封面显示的图片不同)
# 0: 不使用后缀 1: ?加随机数
suffix: 1
# When cover is not set, the default cover is displayed (當沒有設置cover時,默認的封面顯示)
default_cover:
- https://your-domain.vercel.app/类型

再次预览, 会发现每个文章的封面成功显示不一样的图片