效果

volantis

flexcard

通过 hexo new page Pagename创建页面时,需要在Blog/source/Pagename/index.md的Post Front-matter中添加type: “categories”等字样,这其实就是在告诉主题,这个页面是特殊的页面。打开[blogroot]/themes/butterfly/layout/page.pug文件,会看到如下内容

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
extends includes/layout.pug

block content
- const noCardLayout = ['shuoshuo', '404'].includes(page.type) ? 'nc' : ''
- var commentsJsLoad = false

mixin commentLoad
if page.comments !== false && theme.comments.use
- commentsJsLoad = true
!=partial('includes/third-party/comments/index', {}, {cache: true})

#page(class=noCardLayout)
if top_img === false && page.title
.page-title= page.title

case page.type
when 'tags'
include includes/page/tags.pug
+commentLoad
when 'link'
include includes/page/flink.pug
+commentLoad
when 'categories'
include includes/page/categories.pug
+commentLoad
when '404'
include includes/page/404.pug
when 'shuoshuo'
include includes/page/shuoshuo.pug
default
include includes/page/default-page.pug
+commentLoad

可以看到,当一个页面被识别为特殊类型,即when 'categories',就会进入对应的页面。添加新的页面类型就是构建这个特殊页面,即xxx.pug,并添加相应的样式

开始构建

创建页面文件

[blogroot]/themes/butterfly/layout/includes/page文件下新建navigation.pug文件,并添加如下内容

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
#article-container.navigation-widget
if site.data.navigation
each i in site.data.navigation
- var style = i.flink_style || 'volantis'
.flink(class=style)
if i.class_name
h2!= i.class_name
if i.class_desc
.flink-desc!= i.class_desc

if style === 'volantis'
.site-card-group
each item in i.link_list
a.site-card(target='_blank' rel='noopener' href=url_for(item.link))
.img
- var siteshot = item.siteshot ? url_for(item.siteshot) : 'https://image.thum.io/get/width/400/crop/800/allowJPG/wait/20/noanimate/' + item.link
if theme.lazyload.enable
img(data-lazy-src=siteshot onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.post_page) + `'` alt='' )
else
img(src=siteshot onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt='' )
.info
if theme.lazyload.enable
img(data-lazy-src=url_for(item.avatar) onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt='' )
else
img(src=url_for(item.avatar) onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt='' )
span.title= item.name
span.desc(title=item.descr)= item.descr

else if style === 'flexcard'
.flink-list
each item in i.link_list
a.flink-list-card(href=url_for(item.link) target='_blank' data-title=item.descr)
.wrapper.cover
- var siteshot = item.siteshot ? url_for(item.siteshot) : 'https://image.thum.io/get/width/400/crop/800/allowJPG/wait/20/noanimate/' + item.link
if theme.lazyload.enable
img.cover.fadeIn(data-lazy-src=siteshot onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.post_page) + `'` alt='' )
else
img.cover.fadeIn(src=siteshot onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt='' )
.info
if theme.lazyload.enable
img.flink-avatar(data-lazy-src=url_for(item.avatar) onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt='' )
else
img(src=url_for(item.avatar) onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt='' )
span.flink-sitename= item.name

!= page.content

这就是新添加的navigation类型页面的模板

创建样式文件

[blogroot]/themes/butterfly/source/css/_page中新建navigation.styl文件,并添加如下内容

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
230
231
232
233
234
235
.navigation-widget
// =======================
// 公共基础样式
// =======================
.flink
.flink-desc
margin 0.2rem 0 0.5rem

.flink-list
overflow auto
text-align center
padding 0
margin 1rem -6px 0 -6px

.flink-list-item
position relative
float left
overflow hidden
margin 6px 6px
border-radius 12px
border var(--style-border)
box-shadow var(--Jay-shadow-border)
transition 0.3s ease-in-out

.flink-list-item a
display flex
border none
color var(--Jay-fontcolor)
text-decoration none
&:hover
background none

.flink-list-item a img
border-radius 32px
margin 15px 20px 15px 15px
min-width 60px
min-height 60px
transition 0.3s
background var(--Jay-background)
pointer-events none

.flink-list-item:hover a img
width 0
height 0
opacity 0
margin 0.5rem
min-width 0
min-height 0
transition 0.6s

.flink-item-info
max-width 136px
overflow hidden
.flink-list-item:hover .flink-item-info
max-width 100%

.flink-item-name
text-align left
font-size 19px
font-weight 700
white-space nowrap
overflow hidden
text-overflow ellipsis
color var(--Jay-fontcolor)

.flink-list-item:hover a .flink-item-name
color var(--Jay-white)

.flink-item-desc
white-space normal
padding 5px 10px 16px 0
color var(--Jay-fontcolor)
text-align left
height 40px
text-overflow ellipsis
opacity 0.7
display -webkit-box
overflow hidden
-webkit-box-orient vertical
-webkit-line-clamp 2

.flink-list-item:hover a .flink-item-desc
color var(--Jay-white)
overflow inherit
width 100%

// =======================
// volantis 风格
// =======================
.flink.volantis
.site-card-group
display flex
flex-wrap wrap
justify-content flex-start
margin -0.5 * 16px
align-items stretch
.site-card
margin 16px * 0.5
width calc(100% / 4 - 16px)
@media screen and (min-width: 2048px)
width calc(100% / 5 - 16px)
@media screen and (max-width: 768px)
width calc(100% / 3 - 16px)
@media screen and (max-width: 500px)
width calc(100% / 2 - 16px)
display block
line-height 1.4
height 100%
.img
width 100%
height 120px
overflow hidden
border-radius 6px
box-shadow 0 1px 2px rgba(0,0,0,0.2)
background #f6f6f6
img
width 100%
height 100%
object-fit cover
transition transform 2s ease
.info
margin-top 8px
img
width 32px
height 32px
border-radius 16px
float left
margin-right 8px
margin-top 2px
span
display block
.title
font-weight 600
font-size $fontsize-list
color #444
display -webkit-box
-webkit-box-orient vertical
overflow hidden
-webkit-line-clamp 1
.desc
font-size $fontsize-footnote
line-height 1.2
color #888
display -webkit-box
-webkit-box-orient vertical
overflow hidden
-webkit-line-clamp 2
&:hover
.img
box-shadow 0 4px 8px rgba(0,0,0,0.1)
.info .title
color #ff5722

// =======================
// flexcard 风格
// =======================
.flink.flexcard
.flink-list
& > a
width calc(25% - 15px)
height 130px
position relative
display block
margin 15px 7px
float left
overflow hidden
border-radius 10px
transition all 0.3s ease, transform 0.6s cubic-bezier(.6,.2,.1,1)
box-shadow 0 14px 38px rgba(0,0,0,.08),0 3px 8px rgba(0,0,0,.06)
&:hover
.info
transform translateY(-100%)
.wrapper img
transform scale(1.2)
&:before
position fixed
width inherit
margin auto
left 0
right 0
top 10%
border-radius 10px
text-align center
z-index 100
content attr(data-title)
font-size 20px
color #fff
padding 10px
background-color rgba($theme-color,0.8)
.cover
width 100%
transition transform 0.5s ease-out
.wrapper
position relative
.fadeIn
animation coverIn 0.8s ease-out forwards
img
height 130px
.info
display flex
flex-direction column
justify-content center
align-items center
width 100%
height 100%
overflow hidden
border-radius 3px
background-color hsla(0,0%,100%,0.7)
transition transform 0.5s cubic-bezier(.6,.2,.1,1)
img
width 66px
height 66px
border-radius 50%
box-shadow 0 0 10px rgba(0,0,0,0.3)
position relative
top 22px
span
padding 20px 10% 60px 10%
font-size 16px
width 100%
text-align center
background-color hsla(0,0%,100%,0.7)
color var(--font-color)
white-space nowrap
overflow hidden
text-overflow ellipsis

@media screen and (max-width:1024px)
.flink-list > a
width calc(33.33333% - 15px)

@media screen and (max-width:600px)
.flink-list > a
width calc(50% - 15px)

引入新的页面类型

正如前面所说,需要引入才会被主题识别,修改[blogroot]/themes/butterfly/layout/page.pug文件,在相应位置添加

when 'navigation' include includes/page/navigation.pug

修改后的内容,如下所示

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
extends includes/layout.pug

block content
- const noCardLayout = ['shuoshuo', '404'].includes(page.type) ? 'nc' : ''
- var commentsJsLoad = false

mixin commentLoad
if page.comments !== false && theme.comments.use
- commentsJsLoad = true
!=partial('includes/third-party/comments/index', {}, {cache: true})

#page(class=noCardLayout)
if top_img === false && page.title
.page-title= page.title

case page.type
when 'tags'
include includes/page/tags.pug
+commentLoad
when 'link'
include includes/page/flink.pug
+commentLoad
when 'categories'
include includes/page/categories.pug
+commentLoad
when '404'
include includes/page/404.pug
when 'shuoshuo'
include includes/page/shuoshuo.pug
when 'navigation'
include includes/page/navigation.pug
default
include includes/page/default-page.pug
+commentLoad

到此为止新建页面类型已经完成了,自定义的部分主要集中在navigation.pugnavigation.styl中,分别对应页面布局及数据交互页面样式

接下来介绍的是这个页面类型的配置方法

创建navigation页面

在博客的根目录运行

1
hexo new page navigation

运行后会在[blogroot]/source/下生成navigation文件夹,打开navigation文件夹下的index.md文件,按照如下格式添加内容

1
2
3
4
5
6
---
title: 导航
date: 2024-09-06 13:37:37
aside: false
type: 'navigation'
---

为页面添加内容

最后添加页面的内容,即要展示的网页。新建[blogroot]/source/_data/navigation.yml文件(若无data文件夹,新建data文件夹即可),按照如下格式添加内容

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
# class_name 和 class_desc支持 html 格式,如不需要,也可以留空
# siteshot是站点缩略图的链接,留空自动获取站点的缩略图
# flink_style设置站点卡片的样式(volantis或flexcard),不设置默认为volantis

- class_name: 设计素材
class_desc: 为你的设计添加色彩
flink_style:
random: false
link_list:
- name: Font Awesome
link: https://fontawesome.com
avatar: https://www.faviconextractor.com/favicon/fontawesome.com
descr: icon网站
siteshot:
- name: iconfont
link: https://www.iconfont.cn
avatar: https://www.faviconextractor.com/favicon/www.iconfont.cn?larger=true
descr: icon网站
siteshot:

- class_name: 实用工具
class_desc: 非常nice的在线工具
flink_style:
random: false
link_list:
- name: TinyPNG
link: https://tinify.cn
avatar: https://www.faviconextractor.com/favicon/tinify.cn
descr: 图片压缩网站
siteshot:
- name: Favicon Extractor
link: https://www.faviconextractor.com
avatar: https://www.faviconextractor.com/favicon/faviconextractor.com
descr: 网站图标获取
siteshot:

- class_name: 资源网站
class_desc: 帮助构建博客的资源网站
flink_style:
random: false
link_list:
- name: Staticfile CDN
link: https://www.staticfile.net
avatar: https://www.faviconextractor.com/favicon/www.staticfile.net
descr: CDN服务网站
siteshot:

class_nameclass_desc 支持 html 格式,如不需要,也可以留空

siteshot 是站点缩略图的链接,留空自动获取站点的缩略图

flink_style 设置站点卡片的样式( volantisflexcard ),不设置默认为 volantis本文的开头展示了两种样式的效果