Hexo NexT主题美化2.0

最近这段时间,对博客又做了一番魔改,较之前的版本有很大变化。诸如新加的主页轮播图、valine-admin邮件通知、彩色标签页、归档页美化、博客相册、相关文章推荐。小改的地方包括页面分享功能、鼠标样式、类知乎卡片链接及其他页面美化工作等。关于魔改,仁者见仁智者见智吧,有部分喜欢的朋友问我具体的实现逻辑,下面分别总结一下。

PS:本博客 已集成以下所有功能,全动态配置,欢迎star、fork哦~

主页轮播图

  1. 在/themes/next/layout/_macro/目录下,新建carousel.swig文件,拷贝如下内容:
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
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
{% if theme.carousel.enable %}
<script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>

<style type="text/css">

.glyphicon-chevron-left:before{
content: "《"
}
.glyphicon-chevron-right:before{
content: "》"
}

@media (max-width: 767px){
.rights{
display: none;
}
.carousel{
width: 100% !important;
height: 100% !important;
}
.slide{
width: 100% !important;
height: 100% !important;
}

}

.carousel{
width: 100%;
height: 100%;
position: relative;
}

.carousel-inner {
position: relative;
overflow: hidden;
width: 100%;
}
.carousel-inner > .item {
display: none;
position: relative;
-webkit-transition: 0.6s ease-in-out left;
-o-transition: 0.6s ease-in-out left;
transition: 0.6s ease-in-out left;
}
.carousel-inner > .item > img,
.carousel-inner > .item > a > img {
line-height: 1;
}
@media all and (transform-3d), (-webkit-transform-3d) {
.carousel-inner > .item {
-webkit-transition: -webkit-transform 0.6s ease-in-out;
-moz-transition: -moz-transform 0.6s ease-in-out;
-o-transition: -o-transform 0.6s ease-in-out;
transition: transform 0.6s ease-in-out;
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
backface-visibility: hidden;
-webkit-perspective: 1000px;
-moz-perspective: 1000px;
perspective: 1000px;
}
.carousel-inner > .item.next,
.carousel-inner > .item.active.right {
-webkit-transform: translate3d(100%, 0, 0);
transform: translate3d(100%, 0, 0);
left: 0;
}
.carousel-inner > .item.prev,
.carousel-inner > .item.active.left {
-webkit-transform: translate3d(-100%, 0, 0);
transform: translate3d(-100%, 0, 0);
left: 0;
}
.carousel-inner > .item.next.left,
.carousel-inner > .item.prev.right,
.carousel-inner > .item.active {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
left: 0;
}
}
.carousel-inner > .active,
.carousel-inner > .next,
.carousel-inner > .prev {
display: block;
}
.carousel-inner > .active {
left: 0;
}
.carousel-inner > .next,
.carousel-inner > .prev {
position: absolute;
top: 0;
width: 100%;
}
.carousel-inner > .next {
left: 100%;
}
.carousel-inner > .prev {
left: -100%;
}
.carousel-inner > .next.left,
.carousel-inner > .prev.right {
left: 0;
}
.carousel-inner > .active.left {
left: -100%;
}
.carousel-inner > .active.right {
left: 100%;
}
.carousel-control {
position: absolute;
top: 0;
left: 0;
bottom: 0;
width: 15%;
opacity: 0.5;
filter: alpha(opacity=50);
font-size: 20px;
color: #fff;
text-align: center;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
background-color: rgba(0, 0, 0, 0);
}
.carousel-control.left {
background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);
background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);
background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);
}
.carousel-control.right {
left: auto;
right: 0;
background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);
background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);
background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);
}
.carousel-control:hover,
.carousel-control:focus {
outline: 0;
color: #fff;
text-decoration: none;
opacity: 0.9;
filter: alpha(opacity=90);
}
.carousel-control .icon-prev,
.carousel-control .icon-next,
.carousel-control .glyphicon-chevron-left,
.carousel-control .glyphicon-chevron-right {
position: absolute;
top: 50%;
margin-top: -10px;
z-index: 5;
display: inline-block;
}
.carousel-control .icon-prev,
.carousel-control .glyphicon-chevron-left {
left: 50%;
margin-left: -10px;
}
.carousel-control .icon-next,
.carousel-control .glyphicon-chevron-right {
right: 50%;
margin-right: -10px;
}
.carousel-control .icon-prev,
.carousel-control .icon-next {
width: 20px;
height: 20px;
line-height: 1;
font-family: serif;
}
.carousel-control .icon-prev:before {
content: '\2039';
}
.carousel-control .icon-next:before {
content: '\203a';
}
.carousel-indicators {
position: absolute;
bottom: 10px;
left: 50%;
z-index: 15;
width: 60%;
margin-left: -30%;
padding-left: 0;
list-style: none;
text-align: center;
}
.carousel-indicators li {
display: inline-block;
width: 10px;
height: 10px;
margin: 1px;
text-indent: -999px;
border: 1px solid #fff;
border-radius: 10px;
cursor: pointer;
background-color: #000 \9;
background-color: rgba(0, 0, 0, 0);
}
.carousel-indicators .active {
margin: 0;
width: 12px;
height: 12px;
background-color: #fff;
}
.carousel-caption {
position: absolute;
left: 15%;
right: 15%;
bottom: 20px;
z-index: 10;
padding-top: 20px;
padding-bottom: 20px;
color: #fff;
text-align: center;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
}
.carousel-caption .btn {
text-shadow: none;
}
@media screen and (min-width: 768px) {
.carousel-control .glyphicon-chevron-left,
.carousel-control .glyphicon-chevron-right,
.carousel-control .icon-prev,
.carousel-control .icon-next {
width: 30px;
height: 30px;
margin-top: -10px;
font-size: 30px;
}
.carousel-control .glyphicon-chevron-left,
.carousel-control .icon-prev {
margin-left: -10px;
}
.carousel-control .glyphicon-chevron-right,
.carousel-control .icon-next {
margin-right: -10px;
}
.carousel-caption {
left: 20%;
right: 20%;
padding-bottom: 30px;
}
.carousel-indicators {
bottom: 20px;
}
}
</style>
<div width="100%" height="320px" style="border: 0px; overflow: hidden; border-radius: 10px;" scrolling="no">

<div id="myCarousel" class="carousel slide" data-ride="carousel" data-interval="3500" >
<!-- 轮播(Carousel)指标 -->
<ol class="carousel-indicators">
{% set index = 0 %}
{% for item in theme.carousel.item %}

<li data-target="#myCarousel" data-slide-to="{{index}}"></li>
{% set index = index+1 %}

{% endfor %}
</ol>
<!-- 轮播(Carousel)项目 -->
<div class="carousel-inner" style="height: 280px; border-radius: 10px; width: 100%;">

{% set act = 0 %}
{% for item in theme.carousel.item %}

{% if act===0 %}
<a class="item active" href="{{ url_for(item.link) }}" target="_blank" style="height: 100%;">
<img src="{{item.img}}" style="width: 100%; height: 100%" >
</a>
{% set act = 1 %}
{% elseif act===1 %}
<a class="item" href="{{ url_for(item.link) }}" target="_blank" style="height: 100%;">
<img src="{{item.img}}" style="width: 100%; height: 100%;" >
</a>
{% endif %}

{% endfor %}


</div>
<!-- 轮播(Carousel)导航 -->
<a class="left carousel-control" href="#myCarousel" role="button" data-slide="prev">
<span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>

</a>
<a class="right carousel-control" href="#myCarousel" role="button" data-slide="next">
<span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>

</a>
</div>

</div>

{% endif %}
  1. 在/themes/next/layout/index.swig中,找到
1
{% block content %}

在其下方引入新建的carousel.swig文件:

1
2
<!--轮播图-->
{% include '_macro/carousel.swig' %}
  1. 在主题配置文件末尾添加:
1
2
3
4
5
6
7
8
9
10
11
12
13
#Home carousel map, from means link, img means picture
carousel:
enable: true
item: [
{
'link': '文章链接地址',
'img': '图片链接地址'
},
{
'link': '文章链接地址',
'img': '图片链接地址'
}
]

轮播图相应的实现逻辑,可参考Bootstrap官方Carousel实现:

Bootstrap Carousel

可能遇到的问题

  1. the requested content cannot be loaded. please try again later

如点击轮播图出现

KPg5Ax.jpg

可在/themes/next/source/js/src/utils.js的wrapImageWithFancyBox方法中增加以下第8行代码:

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
 wrapImageWithFancyBox: function () {
$('.content img')
.not('[hidden]')
.not('.group-picture img, .post-gallery img')
.each(function () {
var $image = $(this);
/*解决fancybox和图片链接冲突*/
+ if ($(this).hasClass('nofancybox')) return;

var imageTitle = $image.attr('title');
var $imageWrapLink = $image.parent('a');

if ($imageWrapLink.size() < 1) {
var imageLink = ($image.attr('data-original')) ? this.getAttribute('data-original') : this.getAttribute('src');
$imageWrapLink = $image.wrap('<a href="' + imageLink + '"></a>').parent('a');
}

$imageWrapLink.addClass('fancybox fancybox.image');
$imageWrapLink.attr('rel', 'group');

if (imageTitle) {
$imageWrapLink.append('<p class="image-caption">' + imageTitle + '</p>');

//make sure img title tag will show correctly in fancybox
$imageWrapLink.attr('title', imageTitle);
}
});

$('.fancybox').fancybox({
helpers: {
overlay: {
locked: false
}
}
});
}

然后,在carousel.swig中,为img标签加上:

1
class="nofancybox"
  1. 轮播图锚点(被困扰N久)

nlOMHU.gif

点击轮播图左右导航按钮时,a标签的href会锚点到myCarousel处,引起页面滚动。可将href属性改成data-target,如下:

1
<a class="left carousel-control" data-target="#myCarousel" href="javascript:void(0);" role="button" data-slide="prev">

附上我个人的carousel.swig文件,后期将会share至github,欢迎关注。

注意:部分图片可能需要你自己制作,也可以使用我现有的(首页使用浏览器F12查看,位于images目录),样式微调

下载图标
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
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
{% if theme.carousel.enable %}
<script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>

<style type="text/css">

.glyphicon-chevron-left:before{
/* content: "《" */
}
.glyphicon-chevron-right:before{
/* content: "》" */
}

.right-siders{
border-radius: 10px;
/*margin-top: 5px;*/
margin-bottom: 5px;
}

.my-carousel:hover{
margin-left: 5px;
//padding: 5px 1px;
border-radius: 5px;
transform: scale(1.1);
box-shadow: 10px 10px 15px 2px rgba(0,0,0,.12), 0 0 6px 0 rgba(104, 104, 105, 0.1);
}

@media (max-width: 767px){
.rights{
display: none;
}
.carousel{
width: 100% !important;
height: 100% !important;
}
.slide{
width: 100% !important;
height: 100% !important;
}

}

.carousel{
width: 65%;
height: 100%;
position: relative;
}

.carousel-inner {
position: relative;
overflow: hidden;
width: 100%;
}
.carousel-inner > .item {
display: none;
position: relative;
-webkit-transition: 0.6s ease-in-out left;
-o-transition: 0.6s ease-in-out left;
transition: 0.6s ease-in-out left;
}
.carousel-inner > .item > img,
.carousel-inner > .item > a > img {
line-height: 1;
}
@media all and (transform-3d), (-webkit-transform-3d) {
.carousel-inner > .item {
-webkit-transition: -webkit-transform 0.6s ease-in-out;
-moz-transition: -moz-transform 0.6s ease-in-out;
-o-transition: -o-transform 0.6s ease-in-out;
transition: transform 0.6s ease-in-out;
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
backface-visibility: hidden;
-webkit-perspective: 1000px;
-moz-perspective: 1000px;
perspective: 1000px;
}
.carousel-inner > .item.next,
.carousel-inner > .item.active.right {
-webkit-transform: translate3d(100%, 0, 0);
transform: translate3d(100%, 0, 0);
left: 0;
}
.carousel-inner > .item.prev,
.carousel-inner > .item.active.left {
-webkit-transform: translate3d(-100%, 0, 0);
transform: translate3d(-100%, 0, 0);
left: 0;
}
.carousel-inner > .item.next.left,
.carousel-inner > .item.prev.right,
.carousel-inner > .item.active {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
left: 0;
}
}
.carousel-inner > .active,
.carousel-inner > .next,
.carousel-inner > .prev {
display: block;
}
.carousel-inner > .active {
left: 0;
}
.carousel-inner > .next,
.carousel-inner > .prev {
position: absolute;
top: 0;
width: 100%;
}
.carousel-inner > .next {
left: 100%;
}
.carousel-inner > .prev {
left: -100%;
}
.carousel-inner > .next.left,
.carousel-inner > .prev.right {
left: 0;
}
.carousel-inner > .active.left {
left: -100%;
}
.carousel-inner > .active.right {
left: 100%;
}
.carousel-control {
position: absolute;
top: 0;
left: 0;
bottom: 0;
/*width: 5%;*/
opacity: 0.5;
filter: alpha(opacity=50);
font-size: 20px;
color: #fff;
text-align: center;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
background-color: rgba(0, 0, 0, 0);
}
.carousel-control.left {
background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);
background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);
background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#80000000, endColorstr=#00000000, GradientType=1);
}
.carousel-control.right {
left: auto;
right: 0;
background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);
background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);
background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#00000000, endColorstr=#80000000, GradientType=1);
}
.carousel-control:hover,
.carousel-control:focus {
outline: 0;
color: #fff;
text-decoration: none;
opacity: 0.9;
filter: alpha(opacity=90);
}
.carousel-control .icon-prev,
.carousel-control .icon-next,
.carousel-control .glyphicon-chevron-left,
.carousel-control .glyphicon-chevron-right {
position: absolute;
top: 50%;
margin-top: -10px;
z-index: 5;
display: inline-block;
}
/*
.carousel-control .icon-prev,
.carousel-control .glyphicon-chevron-left {
left: 50%;
margin-left: -10px;
}
*/

.carousel-control .icon-prev,
.carousel-control .glyphicon-chevron-left {
background: url('/images/icon-slides.png');
background-position-y: -20px;
left: 9px;
}

/*
.carousel-control .icon-next,
.carousel-control .glyphicon-chevron-right {
right: 50%;
margin-right: -10px;
}
*/

.carousel-control .icon-next,
.carousel-control .glyphicon-chevron-right {
background: url('/images/icon-slides.png');
background-position-x: -50px;
background-position-y: -20px;
right: 0px;
}

.carousel-control .icon-prev,
.carousel-control .icon-next {
width: 20px;
height: 20px;
line-height: 1;
font-family: serif;
}

.carousel-control .icon-prev:before {
content: 2039;
}
.carousel-control .icon-next:before {
content: 203a;
}

.carousel-indicators {
position: absolute;
bottom: 2px;
left: 50%;
z-index: 15;
width: 60%;
margin-left: -30%;
padding-left: 0;
list-style: none;
text-align: center;
}
.carousel-indicators li {
display: inline-block;
width: 30px;
height: 3px;
margin: 5px;
text-indent: -999px;
border: 1px solid #bbb;
border-radius: 10px;
cursor: pointer;
background-color: rgba(0, 0, 0, .24);
}
.carousel-indicators .active {
width: 30px;
height: 3px;
background-color: #fff;
}
.carousel-caption {
position: absolute;
left: 15%;
right: 15%;
bottom: 20px;
z-index: 10;
padding-top: 20px;
padding-bottom: 20px;
color: #fff;
text-align: center;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
}
.carousel-caption .btn {
text-shadow: none;
}
@media screen and (min-width: 768px) {
.carousel-control .glyphicon-chevron-left,
.carousel-control .glyphicon-chevron-right,
.carousel-control .icon-prev,
.carousel-control .icon-next {
width: 30px;
height: 30px;
margin-top: -10px;
font-size: 30px;
}
.carousel-control .glyphicon-chevron-left,
.carousel-control .icon-prev {
margin-left: -10px;
}
.carousel-control .glyphicon-chevron-right,
.carousel-control .icon-next {
/* margin-right: -10px; */
}
.carousel-caption {
left: 20%;
right: 20%;
padding-bottom: 30px;
}
.carousel-indicators {
bottom: -10px;
}
}
</style>

<div width="100%" height="320px" style="border: 0px; overflow: hidden; border-radius: 10px; margin-bottom: 25px;" scrolling="no">

<div id="myCarousel" class="carousel slide" data-ride="carousel" data-interval="3500" style="float:left">

<!-- 轮播(Carousel)指标 -->
<ol class="carousel-indicators">
{% set index = 0 %}
{% for item in theme.carousel.item %}
<li data-target="#myCarousel" data-slide-to="{{index}}"></li>
{% set index = index+1 %}
{% endfor %}
</ol>

<!-- 轮播(Carousel)项目 -->
<div class="carousel-inner" style="height: 280px; border-radius: 10px; width: 100%;">
{% set act = 0 %}
{% for item in theme.carousel.item %}
{% if act===0 %}
<a class="item active" href="{{ url_for(item.link) }}" target="_blank" style="height: 100%;">
{# 添加 class="nofancybox" 解决fancybox和图片链接冲突 #}
<img src="{{item.img}}" class="nofancybox" style="width: 100%; height: 100%" >
</a>
{% set act = 1 %}
{% elseif act===1 %}
<a class="item" href="{{ url_for(item.link) }}" target="_blank" style="height: 100%;">
<img src="{{item.img}}" class="nofancybox" style="width: 100%; height: 100%;" >
</a>
{% endif %}
{% endfor %}
</div>

<!-- 轮播(Carousel)导航 -->
<a class="left carousel-control" data-target="#myCarousel" href="javascript:void(0);" role="button" data-slide="prev">
<span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
</a>
<a class="right carousel-control" data-target="#myCarousel" href="javascript:void(0);" role="button" data-slide="next">
<span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
</a>

</div>

<div class="rights" style="width: 30%; height: 280px; margin-right: 0px;margin-left: 20px;float: left;">
<!-- 天气插件 -->
<iframe width="300px" scrolling="no" height="50px" frameborder="0" allowtransparency="true" src="//i.tianqi.com/index.php?c=code&id=12&color=%23&bdc=%23&icon=1&py=beijing&num=2&site=12"></iframe>

<!-- r热门排行 -->
<div class="my-carousel">
<a href="/top/" target="_blank">
<img class="right-siders nofancybox" src="/images/hot.png" width="100%"/>
</a>
</div>

<!-- 时光留影 -->
<div class="my-carousel">
<a href="/photos/" target="_blank">
<img class="right-siders nofancybox" src="/images/time.png"/>
</a>
</div>

<!-- 小小胡同 -->
<div class="my-carousel">
<a href="/xiaohutong/" target="_blank">
<img class="right-siders nofancybox" src="/images/xiaohutong.png"/>
</a>
</div>

<!-- 推荐阅读 -->
<div class="my-carousel">
<a href="/books/" target="_blank">
<img class="right-siders nofancybox" src="/images/read.png"/>
</a>
</div>

</div>

</div>

{% endif %}

valine-admin

刚接触博客时,使用了多种评论插件,从gitalk到livere(来必力)到valine,一路折腾,最终找到了更喜欢的valine-admin。

Valine Admin 是 Valine 评论系统的扩展和增强,主要实现评论邮件通知、评论管理、垃圾评论过滤等功能。支持完全自定义的邮件通知模板,基于Akismet API实现准确的垃圾评论过滤。

Hexo NexT主题整合步骤如下:

  1. 下载Valine.min.js文件,放到/themes/next/source/js/src/下,也可以上传到自己的服务器或主机上(或者直接使用别人提供的外链)。

  2. 修改/themes/next/layout/_third-party/comments/valine.swig代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{% if theme.valine.enable and theme.valine.appid and theme.valine.appkey %}
<script src="//cdn1.lncld.net/static/js/3.0.4/av-min.js"></script>
<script src="/js/src/Valine.min.js"></script>

<!-- https://deserts.io/diy-a-comment-system/ -->
<script type="text/javascript">
new Valine({
lang: 'zh-cn',
admin_email: '793458585@qq.com', //博主邮箱
el: '#comments' ,
appId: '{{ theme.valine.appid }}',
appKey: '{{ theme.valine.appkey }}',
emoticon_url: 'https://cloud.panjunwen.com/alu',
emoticon_list: ["吐.png","喷血.png","狂汗.png","不说话.png","汗.png","坐等.png","献花.png","不高兴.png","中刀.png","害羞.png","皱眉.png","小眼睛.png","中指.png","尴尬.png","瞅你.png","想一想.png","中枪.png","得意.png","肿包.png","扇耳光.png","亲亲.png","惊喜.png","脸红.png","无所谓.png","便便.png","愤怒.png","蜡烛.png","献黄瓜.png","内伤.png","投降.png","观察.png","看不见.png","击掌.png","抠鼻.png","邪恶.png","看热闹.png","口水.png","抽烟.png","锁眉.png","装大款.png","吐舌.png","无奈.png","长草.png","赞一个.png","呲牙.png","无语.png","阴暗.png","不出所料.png","咽气.png","期待.png","高兴.png","吐血倒地.png","哭泣.png","欢呼.png","黑线.png","喜极而泣.png","喷水.png","深思.png","鼓掌.png","暗地观察.png"],
placeholder: '{{ theme.valine.placeholder }}',
});

</script>
{% endif %}

主题配置文件中的valine可这样配置:

1
2
3
4
5
6
7
8
9
10
valine:
enable: true
appid: your appid #<app_id>
appkey: your appkey #<app_key>
notify: false # mail notifier # 关闭,使用valine-admin发邮件
verify: false # Verification code
placeholder: '&#x270d;写评论' # comment box placeholder
avatar: mm # gravatar style
guest_info: nick,mail,link # custom comment header
pageSize: 10 # pagination size

这样就完成valine替换,不过文章标题下方的评论数会不显示,这功能作者目前没有实现,只能先隐藏,详细教程可参考:

Valine: 独立博客评论系统

有关Valine Admin邮件通知功能,可参考:

Valine Admin 配置手册

我使用的是国际版Leancloud,要对应于北京时间,可相应减8小时,例如我是这样配置:

1
2
# 北京时间每天早8点检查过去24小时内漏发的通知邮件并补发
0 0 0 * * ?
1
2
# 每天早0点到晚23点每隔30分钟访问云引擎
0 0/30 0-23 * * ?

可根据后边的『下次执行时间』进行调配。

附上我个人正在使用的邮件模板和邮件主题

MAIL_TEMPLATE_ADMIN

1
<div style="border-radius: 10px 10px 10px 10px;font-size:13px; color: #555555;width: 666px;font-family:'Century Gothic','Trebuchet MS','Hiragino Sans GB',微软雅黑,'Microsoft Yahei',Tahoma,Helvetica,Arial,'SimSun',sans-serif;margin:50px auto;border:1px solid #eee;max-width:100%;background: #ffffff repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 1px 5px rgba(0, 0, 0, 0.15);"><div style="width:100%;background:#49BDAD;color:#ffffff;border-radius: 10px 10px 0 0;background-image: -moz-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));background-image: -webkit-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));height: 66px;"><p style="font-size:15px;word-break:break-all;padding: 23px 32px;margin:0;background-color: hsla(0,0%,100%,.4);border-radius: 10px 10px 0 0;">您的<a style="text-decoration:none;color: #ffffff;" href="${SITE_URL}"> 『${SITE_NAME}』 </a>上有了新的评论 </p></div><div style="margin:40px auto;width:90%"><p><strong>"${NICK}"</strong> 发表评论:</p><div style="background: #fafafa repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);margin:20px 0px;padding:15px;border-radius:5px;font-size:14px;color:#555555;">${COMMENT}</div><p><a style="text-decoration:none; color:#12addb" href="${POST_URL}" target="_blank">[查看详情]</a></p><style type="text/css">a:link{text-decoration:none}a:visited{text-decoration:none}a:hover{text-decoration:none}a:active{text-decoration:none}</style></div></div>

MAIL_TEMPLATE

1
<div style="border-radius: 10px 10px 10px 10px;font-size:13px;color: #555555;width: 666px;font-family:'Century Gothic','Trebuchet MS','Hiragino Sans GB',微软雅黑,'Microsoft Yahei',Tahoma,Helvetica,Arial,'SimSun',sans-serif;margin:50px auto;border:1px solid #eee;max-width:100%;background: #ffffff repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 1px 5px rgba(0, 0, 0, 0.15);"><div style="width:100%;background:#49BDAD;color:#ffffff;border-radius: 10px 10px 0 0;background-image: -moz-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));background-image: -webkit-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));height: 66px;"><p style="font-size:15px;word-break:break-all;padding: 23px 32px;margin:0;background-color: hsla(0,0%,100%,.4);border-radius: 10px 10px 0 0;">您在<a style="text-decoration:none;color: #ffffff;" href="${SITE_URL}">『${SITE_NAME}』</a>上的留言有新回复啦!!!</p></div><div style="margin:40px auto;width:90%"><p>"<strong>${PARENT_NICK}</strong>" 同学,您曾发表评论:</p><div style="background: #fafafa repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);margin:20px 0px;padding:15px;border-radius:5px;font-size:14px;color:#555555;">${PARENT_COMMENT}</div><p>"<strong>${NICK}</strong>" 给您的回复如下:</p><div style="background: #fafafa repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);margin:20px 0px;padding:15px;border-radius:5px;font-size:14px;color:#555555;">${COMMENT}</div><p>您可以点击:<a style="text-decoration:none; color:#12addb" href="${POST_URL}">[回复的完整内容] </a>进行查看。欢迎再次光临<a style="text-decoration:none; color:#12addb" href="${SITE_URL}"> 『${SITE_NAME}』</a>!!!</p><style type="text/css">a:link{text-decoration:none}a:visited{text-decoration:none}a:hover{text-decoration:none}a:active{text-decoration:none}</style></div></div>

MAIL_SUBJECT_ADMIN

1
叮咚!『${SITE_NAME}』上有了新评论!

MAIL_SUBJECT

1
${PARENT_NICK},您在『${SITE_NAME}』上的评论收到了回复

另外:点击邮件中的链接跳转至相应评论,可在/themes/next/layout/_third-party/comments/valine.swig中添加如下代码:

1
2
3
4
5
6
7
8
9
10
<script>
if(window.location.hash){
var checkExist = setInterval(function() {
if ($(window.location.hash).length) {
$('html, body').animate({scrollTop: $(window.location.hash).offset().top-90}, 1000);
clearInterval(checkExist);
}
}, 100);
}
</script>

具体效果,可在下方的评论区体验哦~

彩色标签页

在/themes/next/layout/目录下,新增tag-color.swig文件,填入如下内容:

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
<script type="text/javascript">
var alltags = document.getElementsByClassName('tag-cloud-tags');
var tags = alltags[0].getElementsByTagName('a');
for (var i = tags.length - 1; i >= 0; i--) {
var r=Math.floor(Math.random()*75+130);
var g=Math.floor(Math.random()*75+100);
var b=Math.floor(Math.random()*75+80);
tags[i].style.background = "rgb("+r+","+g+","+b+")";
}
</script>

<style>
.tag-cloud-tags{
/*font-family: Helvetica, Tahoma, Arial;*/
/*font-weight: 100;*/
text-align: center;
counter-reset: tags;
}
.tag-cloud-tags a{
border-radius: 6px;
padding-right: 5px;
padding-left: 5px;
margin: 8px 5px 0px 0px;
}
.tag-cloud-tags a:before{
content: "🔖";
}

.tag-cloud-tags a:hover{
box-shadow: 0px 5px 15px 0px rgba(0,0,0,.4);
transform: scale(1.1);
/*box-shadow: 10px 10px 15px 2px rgba(0,0,0,.12), 0 0 6px 0 rgba(104, 104, 105, 0.1);*/
transition-duration: 0.15s;
}
</style>

在同级目录的page.swig中引入tag-color.swig:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    <div class="tag-cloud">

<!-- 目前共计xxx个标签
<div class="tag-cloud-title">
{{ _p('counter.tag_cloud', site.tags.length) }}
</div>
-->

<div class="tag-cloud-tags">
{{ tagcloud({min_font: 10, max_font: 15, amount: 300, color: true, start_color: '#ccc', end_color: '#111'}) }}
</div>
</div>

+ {% include 'tag-color.swig' %}

{% elif page.type === 'categories' %}
<div class="category-all-page">
<div class="category-all-title">
{{ _p('counter.categories', site.categories.length) }}
</div>
<div class="category-all">
{{ list_categories() }}
</div>
</div>

hexo三连,打开 我的标签页 看看效果吧

KP2ivQ.jpg

以下是文章底部的标签样式

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
/*文章底部标签样式*/
.posts-expand .post-tags a {
-webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, .12), 0 1px 2px rgba(0, 0, 0, .24);
-moz-box-shadow: 0 1px 3px rgba(0, 0, 0, .12), 0 1px 2px rgba(0, 0, 0, .24);
box-shadow: 0 1px 3px rgba(0, 0, 0, .12), 0 1px 2px rgba(0, 0, 0, .24);
font-family: 'Comic Sans MS', sans-serif;
transition: .2s ease-out;
padding: 3px 5px;
margin: 5px;
background: #f5f5f5;
border-bottom: none;
border-radius: 15px;

+mobile(){
padding: 1px 3px;
font-size: 8px;
}

&:hover {
background: rgba(100,154,182,0.902);
color: #fff;
-webkit-box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2), 0 6px 20px 0 rgba(0,0,0,0.19);
-moz-box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2), 0 6px 20px 0 rgba(0,0,0,0.19);
box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2), 0 6px 20px 0 rgba(0,0,0,0.19);
}
}

代码拷入/themes/next/source/css/_custom/custom.styl即可,效果参考文章末尾处的标签。其它自定义标签样式,可参考:

Hexo NexT主题之自定义标签页

归档页美化

  1. 修改/themes/next/layout/_macro/post-collapse.swig后的代码如下:
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
{% macro render(post) %}

<article class="my-post post-type-{{ post.type | default('normal') }}" itemscope itemtype="http://schema.org/Article">
<header class="my-post-header">

<div class="my-post-meta">
<time class="my-post-time" itemprop="dateCreated"
datetime="{{ moment(post.date).format() }}"
content="{{ date(post.date, config.date_format) }}" >
{{ date(post.date, 'MM-DD') }}
</time>
</div>

<{% if theme.seo %}h3{% else %}h2{% endif %} class="my-post-title">
{% if post.link %}{# Link posts #}
<a class="my-post-title-link post-title-link-external" target="_blank" href="{{ url_for(post.link) }}" itemprop="url">
{{ post.title or post.link }}
<i class="fa fa-external-link"></i>
</a>
{% else %}
<a class="my-post-title-link" href="{{ url_for(post.path) }}" itemprop="url">
{% if post.type === 'picture' %}
{{ post.content }}
{% else %}
<span itemprop="name">{{ post.title | default(__('post.untitled')) }}</span>
{% endif %}
</a>
{% endif %}
</{% if theme.seo %}h3{% else %}h2{% endif %}>

</header>
</article>

{% endmacro %}

主要修改:一是将post-meta这个div移到前面header标签下;二是将所有的class属性都加上my-,例如my-post-meta,这样改动是为了不影响其它页面引用的样式。

  1. 在/themes/next/source/css/_custom/custom.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
/* 归档页样式 began */
.page-archive .archive-page-counter {
font-size: 18px;
background-color: #49b1f5;
padding-left: 10px;
padding-right: 10px;
border-radius: 8px;
color: #fff;
+mobile() {
font-size: 16px;
}
}
.my-post-time{
font-size: 11px;
position: absolute;
color: #fff;
background-color: #49b1f5;
border-radius: 5px;
padding-left: 5px;
padding-right: 5px;
margin-left: 15px;
}
.mypost{
position: relative;
margin-bottom: 1rem;
-webkit-transition: all .2s ease-in-out;
-moz-transition: all .2s ease-in-out;
-o-transition: all .2s ease-in-out;
-ms-transition: all .2s ease-in-out;
transition: all .2s ease-in-out;
}
a.my-post-title-link:before{
top: 10px;
width: 18px;
height: 18px;
content: "📚";
margin-right: 5px;
font: normal normal normal 14px/1 FontAwesome;
font-size: 15px;
line-height: 18px;
}
.my-post:hover{
transform: scale(1.1);
box-shadow: 10px 10px 15px 2px rgba(0,0,0,.12), 0 0 6px 0 rgba(104, 104, 105, 0.1);
border-radius: 30px;
width: 400px;
padding: 1px 10px;
margin-left: 25px;
font-size: 16px;
transition-duration: 0.15s;
+mobile(){
width: 260px;
margin-left: 18px;
}
//display:flex;
}
a.my-post-title-link{
text-decoration: none;
font-size: 15px;
font-weight: 400;
+mobile() {
font-size: 14px;
}
}
.my-post-title{
display: block;
margin-left: 4.5rem;
color: #4c4948;
text-decoration: none;
font-size: .8rem;
cursor: pointer;
+mobile() {
//margin-left: 4rem;
}
}
.my-post-header{
position: top;
margin-bottom: 1rem;
-webkit-transition: all .2s ease-in-out;
-moz-transition: all .2s ease-in-out;
-o-transition: all .2s ease-in-out;
-ms-transition: all .2s ease-in-out;
transition: all .2s ease-in-out;
}
//.my-post-title-link{
// font-size: 16px;
// font-weight: 500;
//}
.my-post-meta{
position: absolute;
color: #99a9bf;
width: 80px;
color: #114142;
}
div.post-block.tag .collection-title h2 {
border-width: 1px;
border-style: solid;
border-color: #3f3f3f;
border-radius: 20px;
font-size: 22px;
background-color: #b4e8fa;
padding: 2px 15px;
letter-spacing: 1.5px;
box-sizing: border-box;
color: #3f3f3f;
display: inline-block;
margin: 10px 0 10px;
text-align: center;
+mobile(){
font-size: 18px;
}
}
.category-list-link:hover{
transform: scale(1.1);
box-shadow: 10px 10px 15px 2px rgba(0,0,0,.12), 0 0 6px 0 rgba(104, 104, 105, 0.1);
border-radius: 8px;
padding: 1px 1px;
margin-left: 5px;
font-size: 16px;
transition-duration: 0.15s;
//display:flex;
}
/* 归档页样式 end */

根据需要调整对应的样式,效果可查看:

归档页样式效果

博客相册

相册功能可参考兰州小红鸡的博客,使用的是腾讯云cos作为相册存储桶。实名认证后,赠送50GB标准存储容量,有效期6个月,但是访问或下载对象产生的外网下行流量是单独计费的,可以购买COS下行流量包,具体可参考官网。

相册调试开始的这两天,我每天刷掉了5G左右的流量,费用大概5块钱吧,欠费第二天就被禁用了,需要充值缴费,要么删数据。腾讯嘛,你懂的。虽然流量也不是很贵,但对我这种负债累累的来说,照这速度,日积月累也多呀。还是想想其他办法吧,免费的用惯了,哈哈~

期间也考虑使用七牛云图床,对象存储的官方SDK挺全,也能通过api获取到图片。主要是不想整这么复杂,再者我还没绑定域名,其融合CDN加速域名会在30个自然日后自动回收。当然了,它的CDN-HTTP流量也是按量收费,貌似没腾讯的贵。基本是类似的一个套路吧。

考虑到自己这相册也不常用,放上些个性化图片就行,无需经常更新,所以就选择用免费的图床链接来实现。贴上完整代码:

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
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
<style type="text/css">

.header-inner{
display: none;
}
.sidebar{
display: none;
}
.content{
margin-bottom: 360px;
}
.content-wrap{
width: 100%;
// box-sizing: content-box;
padding: initial !important;
background:url('https://s2.ax1x.com/2019/09/07/nlL4pR.jpg');
}

.main-inner{
width: 100%;
}
.main {
padding-bottom: 150px;
margin-top: 0px;
background:url('https://s2.ax1x.com/2019/09/07/nlL4pR.jpg');
}
.main-inner{
margin-top: unset;
}
.page-post-detail .post-meta{
display: none;
}
body {
background-image: unset;
background-attachment: unset;
background-size: 100%;
/*background-position: top left;*/
}
.header{
background: rgba(28, 25, 25, 0.6);
border-bottom: unset;
}
.menu .menu-item a{
font-weight: 300;
color: #e6eaed;
}
.footer-inner {
padding-left: 0px;
}

img:hover {
//opacity:0.8; /*透明度*/
//filter:alpha(opacity=100); /* For IE8 and earlier */
}

.imgbox{
margin-top: 20px;
padding: 1px 10px;
width: 100%;
overflow: hidden;
height: 250px;
border-right: 1px solid #bcbcbc;
background:url('https://s2.ax1x.com/2019/09/07/nlL4pR.jpg');
}
.box{
visibility: visible;
overflow: auto;
zoom: 1;
}
.box li{
float: left;
width: 25%;
position: relative;
overflow: hidden;
text-align: center;
list-style: none;
margin: 0;
/*display: inline;*/
padding: 0;
height: 360px;
}
.box li span{
display: block;
padding: 12% 7% 10% 7%;
min-height: 80px;
//background: #fff;
color: #fff;
font-size: 16px;
font-weight: 600;
line-height: 26px;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}

img.imgitem{
padding: unset;
padding: unset;
border: unset;
position: relative;
padding: 0px;
height: auto;
width: 100%;
}

div#posts.posts-expand {
border: unset;
padding: unset;
margin-bottom: 10px;
}
.posts-expand .post-body img{
padding: 0px !important;
}
.box p{
margin-top: -25px;
display: block;
background: #121212;
color: #fff;
font-size: 14px;
-webkit-box-sizing: border-box;
box-sizing: border-box;
text-align: center;
}

.box span strong{
background: rgba(0,0,0,0.4);
padding: 20px;
}

.posts-expand .post-title {
display: none;
}

.title{
margin: 10px auto;
display: inline-block;
vertical-align: middle;
//background: url(/images/beichen.jpg);
font: 85px/250px 'ChaletComprimeMilanSixty';
//background-position: left bottom !important;
background-position: center center !important;
color: #fff;
background-size: 100% auto !important;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
width: 100%;
text-align: center;
border: unset;
height: 560px;
cursor: unset !important;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}

@media (max-width: 767px){
.box li {
width: 98%;
}
.title {
height: 200px;
}

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

}
.posts-expand {
margin: unset;
}

}

@media (min-width: 1600px){

.container .main-inner{
width: 100%;
}
}

</style>

<div id="box" class="box"></div>

<script type="text/javascript">

// 相册json
var json =
[
[
{
'title': '七彩丹霞',
'url': 'https://s2.ax1x.com/2019/09/07/nlRzZt.jpg'
},
{
'title': '9月雨后',
'url': 'https://s2.ax1x.com/2019/09/07/nlRvqI.jpg'
},
{
'title': '五花肉',
'url': 'https://s2.ax1x.com/2019/09/07/nlRbGD.jpg'
},
{
'title': '五花肉+1',
'url': 'https://s2.ax1x.com/2019/09/07/nlRHPO.jpg'
},
{
'title': '别样的艳',
'url': 'https://s2.ax1x.com/2019/09/07/nlRTIK.jpg'
},
{
'title': '远处的城堡',
'url': 'https://s2.ax1x.com/2019/09/07/nlRXMd.md.jpg'
},
{
'title': '夕阳红',
'url': 'https://s2.ax1x.com/2019/09/07/nlRqRe.md.jpg'
},
{
'title': '卢浮宫',
'url': 'https://s2.ax1x.com/2019/09/07/nlRIVx.md.jpg'
},
{
'title': '景区一角',
'url': 'https://s2.ax1x.com/2019/09/07/nlRhrR.md.jpg'
},
{
'title': '夕阳🌇',
'url': 'https://s2.ax1x.com/2019/09/07/nlRbGD.md.jpg'
},
{
'title': '冰沟丹霞',
'url': 'https://s2.ax1x.com/2019/09/07/nlRLxH.md.jpg'
},
{
'title': '别样的雨后',
'url': 'https://s2.ax1x.com/2019/09/07/nlRRxJ.md.jpg'
},
{
'title': '卢浮宫',
'url': 'https://s2.ax1x.com/2019/09/07/nlR4q1.md.jpg'
}
],

[
{
'title': '世界之巅',
'url': 'https://s2.ax1x.com/2019/09/07/nl5540.md.jpg'
},
{
'title': '一天的行程',
'url': 'https://s2.ax1x.com/2019/09/07/nl56gS.md.jpg'
},
{
'title': '珠峰国家公园',
'url': 'https://s2.ax1x.com/2019/09/07/nl5RBj.md.jpg'
},
{
'title': '盘山公路',
'url': 'https://s2.ax1x.com/2019/09/07/nl54Nq.md.jpg'
},
{
'title': '保护区',
'url': 'https://s2.ax1x.com/2019/09/07/nl5LDJ.md.png'
},
{
'title': '珠峰大本营',
'url': 'https://s2.ax1x.com/2019/09/07/nlINGV.md.png'
},
{
'title': '氧气瓶',
'url': 'https://s2.ax1x.com/2019/09/07/nl5jER.md.jpg'
},
{
'title': '珠峰日出',
'url': 'https://s2.ax1x.com/2019/09/07/nl5cjg.md.jpg'
},
{
'title': '海拔最高的寺庙—绒布寺',
'url': 'https://s2.ax1x.com/2019/09/07/nl5hEn.md.jpg'
}
]
]

var content = json2Array(json);

var wid = 250;
if ((window.innerWidth) > 1200) {
wid = (window.innerWidth*3)/18;
}
var box = document.getElementById('box');

var i=0;
for (var i = 0; i < content.length; i++) {
var conBox = document.createElement("div");
conBox.id = 'conBox'+i;
box.appendChild(conBox);
var item = document.createElement("div");
var title = content[i][0].title;
var url = content[i][0].url;
item.innerHTML = "<button class = 'title' style = 'background: url(" + url + ");'><span style = 'display: inline;'><strong style = 'color:#f0f3f6;' >" + title + "</strong></span></button>";
conBox.appendChild(item);

for (var j = 1; j < content[i].length ; j++) {
var _title = content[i][j].title;
var _url = content[i][j].url;
var item = document.createElement("li");
item.innerHTML="<div class = 'imgbox' id = 'imgbox' style = 'height: " + wid + "px;'><img class = 'imgitem' src='" + _url + "' alt='" + _url + "'></div><span>" + _title +"</span>";
conBox.appendChild(item);
}
}

//json转二维数组
function json2Array(arr) {
for (var i=0; i<arr.length; i++) {
var tmpArr = []
for (var attr in arr[i]) {
tmpArr.push(arr[i][attr])
}
arr[i] = tmpArr
}
return arr
}

</script>

部分逻辑参考小红鸡的做法,这里代码做了简化,将图片标题、链接写成json格式即可。自定义排序,拷贝代码到你的博客即可看到效果,其他样式按需修改,效果:

我的相册——时光留影

文章推荐

文章结束时,开启相关文章推荐功能,会根据文章标签的相关度推荐相关的文章,效果像这样:

KP2m5V.jpg

  1. 该功能需要依赖hexo-related-popular-posts插件:
1
npm install hexo-related-popular-posts --save
  1. 在/themes/next/layout/_macro/目录下,新建post-related.swig文件,内容如下:
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
{% set popular_posts = popular_posts_json(theme.related_posts.params, post) %}
{% if popular_posts.json and popular_posts.json.length > 0 %}
<div class="popular-posts-header">
<i class="fa fa-{{ theme.related_posts.icon }}"></i>
{{ theme.related_posts.title | default(__('post.related_posts')) }}
</div>

<details>
<summary>点击查看</summary>
<ul class="popular-posts">
{% for popular_post in popular_posts.json %}
<li class="popular-posts-item">
{% if popular_post.date and popular_post.date != '' %}
<div class="popular-posts-date">{{ popular_post.date }}</div>
{% endif %}
{% if popular_post.img && popular_post.img != '' %}
<div class="popular-posts-img"><img src="{{ popular_post.img }}" /></div>
{% endif %}
<div class="popular-posts-title"><a href="{{ popular_post.path }}" rel="bookmark">{{ popular_post.title }}</a></div>
{% if popular_post.excerpt && popular_post.excerpt != '' %}
<div class="popular-posts-excerpt"><p>{{ popular_post.excerpt }}</p></div>
{% endif %}
</li>
{% endfor %}
</ul>
</details>

{% endif %}

在同级别的post.swig中END POST BODY上方(POST文章末尾)引入:

1
2
3
4
 <!-- 相关文章推荐 -->
{% if theme.related_posts.enable and (theme.related_posts.display_in_home or not is_index) %}
{% include 'post-related.swig' with { post: post } %}
{% endif %}
  1. 主题配置文件末尾加入如下配置:
1
2
3
4
5
6
7
8
9
10
11
12
# Dependencies: https://github.com/tea3/hexo-related-popular-posts
related_posts:
enable: true
title: 相关文章
icon: graduation-cap
display_in_home: false
params:
maxCount: 10
#PPMixingRate: 0.0
#isDate: false
#isImage: false
#isExcerpt: false
  1. 可选配置,在/themes/next/source/css/_custom/custom.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
/*相关文章推荐 pc样式设置*/
summary{
outline: 0;
cursor: pointer;
margin-top: 15px;
+mobile() {/*手机端*/
font-size: 14px;
margin-top: 10px;
}
}
details{
margin-left: 20px;
}
details .popular-posts{
+mobile() {
margin: 5px -12px;
}
}
.popular-posts-header {
margin-top: 45px;
font-size: 20px;
font-weight: 900;
border-bottom: 1px solid #eee;
+mobile() {/*手机端*/
font-size: 18px;
margin-top: 25px;
}
}
ul.popular-posts .popular-posts-item .popular-posts-title a {
border-bottom: 1px solid #999;
&:hover{
border-bottom: none;
}
}

shareJS分享

之前用的百度分享样式不大美观,加载不稳定,不支持https(虽然改好了)等多种原因,遂使用shareJS进行了替换,文档里提供了多种安装方式,简单说下我在博客中整合的步骤。

  1. github下载zip文件,将解压的文件夹dist放到博客/themes/next/source/目录

  2. 在/themes/next/layout/_layout.swig中body标签内部引入:

1
2
3
<!--share.js-->
<link rel="stylesheet" href="/dist/css/share.min.css">
<script src="/dist/js/social-share.min.js"></script>
  1. 在/themes/next/layout/_partials/share/目录下新增sharejs.swig文件,添加如下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<div
data-weibo-title="分享到微博"
data-qq-title="分享到QQ"
data-douban-title="分享到豆瓣"
class="social-share"
class="share-component"

{#
data-disabled="twitter,facebook"
#}

data-disabled="qzone,google+,linkedin"
data-description="Share.js - 一键分享到微博,QQ空间,腾讯微博,人人,豆瓣...">
分享到:
</div>
  1. 在/themes/next/layout/post.swig中<div class="post-spread">标签内部endif前引入:
1
2
{% elseif theme.share_js %}
{% include '_partials/share/sharejs.swig' %}
  1. 主题配置文件增加:
1
share_js: true

鼠标样式

在 /themes/next/source/css/_custom/custom.styl 添加样式:

1
2
3
4
5
6
7
/* 鼠标样式 */
* {
cursor: url(/images/default.cur),auto;
}
:link {
cursor: url(/images/pointer.cur),auto
}

用到的两个文件:default.cur、pointer.cur 位于 images 目录下,因为是 .cur 这种静态光标文件,编辑器打开是一堆 ASCII 码,这里就不贴了,直接附上链接,当然,你也可以在浏览器里获取。

default.cur pointer.cur

鼠标点击特效(4种)

常用的 4 种特效为大家所列如下:

鼠标点击特效

在主题 _config.yml 中添加动态配置项:

1
2
3
cursor_effect:
enabled: true
type: love # fireworks:礼花 | explosion:爆炸 | love:浮出爱心 | text:浮出文字

在 /themes/next/layout/_custom/custom.swig 中,添加如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
{% if theme.cursor_effect %}
{% if theme.cursor_effect.type == "fireworks" %}
<script src="/js/cursor/fireworks.js"></script>
{% elseif theme.cursor_effect.type == "explosion" %}
<canvas class="fireworks" style="position: fixed;left: 0;top: 0;z-index: 1; pointer-events: none;" ></canvas>
<script src="//cdn.bootcss.com/animejs/2.2.0/anime.min.js"></script>
<script src="/js/cursor/explosion.min.js"></script>
{% elseif theme.cursor_effect.type == "love" %}
<script src="/js/cursor/love.min.js"></script>
{% elseif theme.cursor_effect.type == "text" %}
<script src="/js/cursor/text.js"></script>
{% endif %}
{% endif %}

如果是第一次使用这个 custom.swig,则需要在 /themes/next/layout/_layout.swig 中引入

1
{% include '_custom/custom.swig' %}

这里主要用到 /themes/next/source/js/cursor/ 目录的 4 个 JS 文件,下边分别贴一下代码

fireworks.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
147
148
149
150
151
152
153
154
class Circle {
constructor({ origin, speed, color, angle, context }) {
this.origin = origin
this.position = { ...this.origin }
this.color = color
this.speed = speed
this.angle = angle
this.context = context
this.renderCount = 0
}

draw() {
this.context.fillStyle = this.color
this.context.beginPath()
this.context.arc(this.position.x, this.position.y, 2, 0, Math.PI * 2)
this.context.fill()
}

move() {
this.position.x = (Math.sin(this.angle) * this.speed) + this.position.x
this.position.y = (Math.cos(this.angle) * this.speed) + this.position.y + (this.renderCount * 0.3)
this.renderCount++
}
}

class Boom {
constructor ({ origin, context, circleCount = 16, area }) {
this.origin = origin
this.context = context
this.circleCount = circleCount
this.area = area
this.stop = false
this.circles = []
}

randomArray(range) {
const length = range.length
const randomIndex = Math.floor(length * Math.random())
return range[randomIndex]
}

randomColor() {
const range = ['8', '9', 'A', 'B', 'C', 'D', 'E', 'F']
return '#' + this.randomArray(range) + this.randomArray(range) + this.randomArray(range) + this.randomArray(range) + this.randomArray(range) + this.randomArray(range)
}

randomRange(start, end) {
return (end - start) * Math.random() + start
}

init() {
for(let i = 0; i < this.circleCount; i++) {
const circle = new Circle({
context: this.context,
origin: this.origin,
color: this.randomColor(),
angle: this.randomRange(Math.PI - 1, Math.PI + 1),
speed: this.randomRange(1, 6)
})
this.circles.push(circle)
}
}

move() {
this.circles.forEach((circle, index) => {
if (circle.position.x > this.area.width || circle.position.y > this.area.height) {
return this.circles.splice(index, 1)
}
circle.move()
})
if (this.circles.length == 0) {
this.stop = true
}
}

draw() {
this.circles.forEach(circle => circle.draw())
}
}

class CursorSpecialEffects {
constructor() {
this.computerCanvas = document.createElement('canvas')
this.renderCanvas = document.createElement('canvas')

this.computerContext = this.computerCanvas.getContext('2d')
this.renderContext = this.renderCanvas.getContext('2d')

this.globalWidth = window.innerWidth
this.globalHeight = window.innerHeight

this.booms = []
this.running = false
}

handleMouseDown(e) {
const boom = new Boom({
origin: { x: e.clientX, y: e.clientY },
context: this.computerContext,
area: {
width: this.globalWidth,
height: this.globalHeight
}
})
boom.init()
this.booms.push(boom)
this.running || this.run()
}

handlePageHide() {
this.booms = []
this.running = false
}

init() {
const style = this.renderCanvas.style
style.position = 'fixed'
style.top = style.left = 0
style.zIndex = '999999999999999999999999999999999999999999'
style.pointerEvents = 'none'

style.width = this.renderCanvas.width = this.computerCanvas.width = this.globalWidth
style.height = this.renderCanvas.height = this.computerCanvas.height = this.globalHeight

document.body.append(this.renderCanvas)

window.addEventListener('mousedown', this.handleMouseDown.bind(this))
window.addEventListener('pagehide', this.handlePageHide.bind(this))
}

run() {
this.running = true
if (this.booms.length == 0) {
return this.running = false
}

requestAnimationFrame(this.run.bind(this))

this.computerContext.clearRect(0, 0, this.globalWidth, this.globalHeight)
this.renderContext.clearRect(0, 0, this.globalWidth, this.globalHeight)

this.booms.forEach((boom, index) => {
if (boom.stop) {
return this.booms.splice(index, 1)
}
boom.move()
boom.draw()
})
this.renderContext.drawImage(this.computerCanvas, 0, 0, this.globalWidth, this.globalHeight)
}
}

const cursorSpecialEffects = new CursorSpecialEffects()
cursorSpecialEffects.init()
explosion.min.js
1
"use strict";function updateCoords(e){pointerX=(e.clientX||e.touches[0].clientX)-canvasEl.getBoundingClientRect().left,pointerY=e.clientY||e.touches[0].clientY-canvasEl.getBoundingClientRect().top}function setParticuleDirection(e){var t=anime.random(0,360)*Math.PI/180,a=anime.random(50,180),n=[-1,1][anime.random(0,1)]*a;return{x:e.x+n*Math.cos(t),y:e.y+n*Math.sin(t)}}function createParticule(e,t){var a={};return a.x=e,a.y=t,a.color=colors[anime.random(0,colors.length-1)],a.radius=anime.random(16,32),a.endPos=setParticuleDirection(a),a.draw=function(){ctx.beginPath(),ctx.arc(a.x,a.y,a.radius,0,2*Math.PI,!0),ctx.fillStyle=a.color,ctx.fill()},a}function createCircle(e,t){var a={};return a.x=e,a.y=t,a.color="#F00",a.radius=0.1,a.alpha=0.5,a.lineWidth=6,a.draw=function(){ctx.globalAlpha=a.alpha,ctx.beginPath(),ctx.arc(a.x,a.y,a.radius,0,2*Math.PI,!0),ctx.lineWidth=a.lineWidth,ctx.strokeStyle=a.color,ctx.stroke(),ctx.globalAlpha=1},a}function renderParticule(e){for(var t=0;t<e.animatables.length;t++){e.animatables[t].target.draw()}}function animateParticules(e,t){for(var a=createCircle(e,t),n=[],i=0;i<numberOfParticules;i++){n.push(createParticule(e,t))}anime.timeline().add({targets:n,x:function(e){return e.endPos.x},y:function(e){return e.endPos.y},radius:0.1,duration:anime.random(1200,1800),easing:"easeOutExpo",update:renderParticule}).add({targets:a,radius:anime.random(80,160),lineWidth:0,alpha:{value:0,easing:"linear",duration:anime.random(600,800)},duration:anime.random(1200,1800),easing:"easeOutExpo",update:renderParticule,offset:0})}function debounce(e,t){var a;return function(){var n=this,i=arguments;clearTimeout(a),a=setTimeout(function(){e.apply(n,i)},t)}}var canvasEl=document.querySelector(".fireworks");if(canvasEl){var ctx=canvasEl.getContext("2d"),numberOfParticules=30,pointerX=0,pointerY=0,tap="mousedown",colors=["#FF1461","#18FF92","#5A87FF","#FBF38C"],setCanvasSize=debounce(function(){canvasEl.width=2*window.innerWidth,canvasEl.height=2*window.innerHeight,canvasEl.style.width=window.innerWidth+"px",canvasEl.style.height=window.innerHeight+"px",canvasEl.getContext("2d").scale(2,2)},500),render=anime({duration:1/0,update:function(){ctx.clearRect(0,0,canvasEl.width,canvasEl.height)}});document.addEventListener(tap,function(e){"sidebar"!==e.target.id&&"toggle-sidebar"!==e.target.id&&"A"!==e.target.nodeName&&"IMG"!==e.target.nodeName&&(render.play(),updateCoords(e),animateParticules(pointerX,pointerY))},!1),setCanvasSize(),window.addEventListener("resize",setCanvasSize,!1)}"use strict";function updateCoords(e){pointerX=(e.clientX||e.touches[0].clientX)-canvasEl.getBoundingClientRect().left,pointerY=e.clientY||e.touches[0].clientY-canvasEl.getBoundingClientRect().top}function setParticuleDirection(e){var t=anime.random(0,360)*Math.PI/180,a=anime.random(50,180),n=[-1,1][anime.random(0,1)]*a;return{x:e.x+n*Math.cos(t),y:e.y+n*Math.sin(t)}}function createParticule(e,t){var a={};return a.x=e,a.y=t,a.color=colors[anime.random(0,colors.length-1)],a.radius=anime.random(16,32),a.endPos=setParticuleDirection(a),a.draw=function(){ctx.beginPath(),ctx.arc(a.x,a.y,a.radius,0,2*Math.PI,!0),ctx.fillStyle=a.color,ctx.fill()},a}function createCircle(e,t){var a={};return a.x=e,a.y=t,a.color="#F00",a.radius=0.1,a.alpha=0.5,a.lineWidth=6,a.draw=function(){ctx.globalAlpha=a.alpha,ctx.beginPath(),ctx.arc(a.x,a.y,a.radius,0,2*Math.PI,!0),ctx.lineWidth=a.lineWidth,ctx.strokeStyle=a.color,ctx.stroke(),ctx.globalAlpha=1},a}function renderParticule(e){for(var t=0;t<e.animatables.length;t++){e.animatables[t].target.draw()}}function animateParticules(e,t){for(var a=createCircle(e,t),n=[],i=0;i<numberOfParticules;i++){n.push(createParticule(e,t))}anime.timeline().add({targets:n,x:function(e){return e.endPos.x},y:function(e){return e.endPos.y},radius:0.1,duration:anime.random(1200,1800),easing:"easeOutExpo",update:renderParticule}).add({targets:a,radius:anime.random(80,160),lineWidth:0,alpha:{value:0,easing:"linear",duration:anime.random(600,800)},duration:anime.random(1200,1800),easing:"easeOutExpo",update:renderParticule,offset:0})}function debounce(e,t){var a;return function(){var n=this,i=arguments;clearTimeout(a),a=setTimeout(function(){e.apply(n,i)},t)}}var canvasEl=document.querySelector(".fireworks");if(canvasEl){var ctx=canvasEl.getContext("2d"),numberOfParticules=30,pointerX=0,pointerY=0,tap="mousedown",colors=["#FF1461","#18FF92","#5A87FF","#FBF38C"],setCanvasSize=debounce(function(){canvasEl.width=2*window.innerWidth,canvasEl.height=2*window.innerHeight,canvasEl.style.width=window.innerWidth+"px",canvasEl.style.height=window.innerHeight+"px",canvasEl.getContext("2d").scale(2,2)},500),render=anime({duration:1/0,update:function(){ctx.clearRect(0,0,canvasEl.width,canvasEl.height)}});document.addEventListener(tap,function(e){"sidebar"!==e.target.id&&"toggle-sidebar"!==e.target.id&&"A"!==e.target.nodeName&&"IMG"!==e.target.nodeName&&(render.play(),updateCoords(e),animateParticules(pointerX,pointerY))},!1),setCanvasSize(),window.addEventListener("resize",setCanvasSize,!1)};
love.min.js
1
!function(e,t,a){function n(){c(".heart{width: 10px;height: 10px;position: fixed;background: #f00;transform: rotate(45deg);-webkit-transform: rotate(45deg);-moz-transform: rotate(45deg);}.heart:after,.heart:before{content: '';width: inherit;height: inherit;background: inherit;border-radius: 50%;-webkit-border-radius: 50%;-moz-border-radius: 50%;position: fixed;}.heart:after{top: -5px;}.heart:before{left: -5px;}"),o(),r()}function r(){for(var e=0;e<d.length;e++)d[e].alpha<=0?(t.body.removeChild(d[e].el),d.splice(e,1)):(d[e].y--,d[e].scale+=.004,d[e].alpha-=.013,d[e].el.style.cssText="left:"+d[e].x+"px;top:"+d[e].y+"px;opacity:"+d[e].alpha+";transform:scale("+d[e].scale+","+d[e].scale+") rotate(45deg);background:"+d[e].color+";z-index:99999");requestAnimationFrame(r)}function o(){var t="function"==typeof e.onclick&&e.onclick;e.onclick=function(e){t&&t(),i(e)}}function i(e){var a=t.createElement("div");a.className="heart",d.push({el:a,x:e.clientX-5,y:e.clientY-5,scale:1,alpha:1,color:s()}),t.body.appendChild(a)}function c(e){var a=t.createElement("style");a.type="text/css";try{a.appendChild(t.createTextNode(e))}catch(t){a.styleSheet.cssText=e}t.getElementsByTagName("head")[0].appendChild(a)}function s(){return"rgb("+~~(255*Math.random())+","+~~(255*Math.random())+","+~~(255*Math.random())+")"}var d=[];e.requestAnimationFrame=function(){return e.requestAnimationFrame||e.webkitRequestAnimationFrame||e.mozRequestAnimationFrame||e.oRequestAnimationFrame||e.msRequestAnimationFrame||function(e){setTimeout(e,1e3/60)}}(),n()}(window,document);
text.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
var a_idx = 0;
jQuery(document).ready(function($) {
$("body").click(function(e) {
var a = new Array("富强", "民主", "文明", "和谐", "自由", "平等", "公正" ,"法治", "爱国", "敬业", "诚信", "友善");
var $i = $("<span/>").text(a[a_idx]);
var x = e.pageX,
y = e.pageY;
$i.css({
"z-index": 99999,
"top": y - 28,
"left": x - a[a_idx].length * 8,
"position": "absolute",
"color": "#ff7a45"
});
$("body").append($i);
$i.animate({
"top": y - 180,
"opacity": 0
}, 1500, function() {
$i.remove();
});
a_idx = (a_idx + 1) % a.length;
});
});

打字特效 (评论、留言)

此功能主要通过 JS 监听页面的 input 输入框事件来实现。首先在主题 _config.yml 中添加动态配置项

1
2
3
4
typing_effect:
enabled: true
colorful: true # 礼花
shake: false # 震动

在 /themes/next/layout/_custom/custom.swig 中引入依赖

1
2
3
4
5
6
7
8
{% if theme.typing_effect %}
<script src="/js/src/activate-power-mode.min.js"></script>
<script>
POWERMODE.colorful = {{ theme.typing_effect.colorful }};
POWERMODE.shake = {{ theme.typing_effect.shake }};
document.body.addEventListener('input', POWERMODE);
</script>
{% endif %}

其中的 activate-power-mode.min.js 位于 /themes/next/source/js/src/ 目录,代码如下:

1
(function webpackUniversalModuleDefinition(root,factory){if(typeof exports==='object'&&typeof module==='object')module.exports=factory();else if(typeof define==='function'&&define.amd)define([],factory);else if(typeof exports==='object')exports["POWERMODE"]=factory();else root["POWERMODE"]=factory()})(this,function(){return(function(modules){var installedModules={};function __webpack_require__(moduleId){if(installedModules[moduleId])return installedModules[moduleId].exports;var module=installedModules[moduleId]={exports:{},id:moduleId,loaded:false};modules[moduleId].call(module.exports,module,module.exports,__webpack_require__);module.loaded=true;return module.exports}__webpack_require__.m=modules;__webpack_require__.c=installedModules;__webpack_require__.p="";return __webpack_require__(0)})([function(module,exports,__webpack_require__){'use strict';var canvas=document.createElement('canvas');canvas.width=window.innerWidth;canvas.height=window.innerHeight;canvas.style.cssText='position:fixed;top:0;left:0;pointer-events:none;z-index:999999';window.addEventListener('resize',function(){canvas.width=window.innerWidth;canvas.height=window.innerHeight});document.body.appendChild(canvas);var context=canvas.getContext('2d');var particles=[];var particlePointer=0;POWERMODE.shake=true;function getRandom(min,max){return Math.random()*(max-min)+min}function getColor(el){if(POWERMODE.colorful){var u=getRandom(0,360);return'hsla('+getRandom(u-10,u+10)+', 100%, '+getRandom(50,80)+'%, '+1+')'}else{return window.getComputedStyle(el).color}}function getCaret(){var el=document.activeElement;var bcr;if(el.tagName==='TEXTAREA'||(el.tagName==='INPUT'&&el.getAttribute('type')==='text')){var offset=__webpack_require__(1)(el,el.selectionStart);bcr=el.getBoundingClientRect();return{x:offset.left+bcr.left,y:offset.top+bcr.top,color:getColor(el)}}var selection=window.getSelection();if(selection.rangeCount){var range=selection.getRangeAt(0);var startNode=range.startContainer;if(startNode.nodeType===document.TEXT_NODE){startNode=startNode.parentNode}bcr=range.getBoundingClientRect();return{x:bcr.left,y:bcr.top,color:getColor(startNode)}}return{x:0,y:0,color:'transparent'}}function createParticle(x,y,color){return{x:x,y:y,alpha:1,color:color,velocity:{x:-1+Math.random()*2,y:-3.5+Math.random()*2}}}function POWERMODE(){{var caret=getCaret();var numParticles=5+Math.round(Math.random()*10);while(numParticles--){particles[particlePointer]=createParticle(caret.x,caret.y,caret.color);particlePointer=(particlePointer+1)%500}}{if(POWERMODE.shake){var intensity=1+2*Math.random();var x=intensity*(Math.random()>0.5?-1:1);var y=intensity*(Math.random()>0.5?-1:1);document.body.style.marginLeft=x+'px';document.body.style.marginTop=y+'px';setTimeout(function(){document.body.style.marginLeft='';document.body.style.marginTop=''},75)}}};POWERMODE.colorful=false;function loop(){requestAnimationFrame(loop);context.clearRect(0,0,canvas.width,canvas.height);for(var i=0;i<particles.length;++i){var particle=particles[i];if(particle.alpha<=0.1)continue;particle.velocity.y+=0.075;particle.x+=particle.velocity.x;particle.y+=particle.velocity.y;particle.alpha*=0.96;context.globalAlpha=particle.alpha;context.fillStyle=particle.color;context.fillRect(Math.round(particle.x-1.5),Math.round(particle.y-1.5),3,3)}}requestAnimationFrame(loop);module.exports=POWERMODE},function(module,exports){(function(){var properties=['direction','boxSizing','width','height','overflowX','overflowY','borderTopWidth','borderRightWidth','borderBottomWidth','borderLeftWidth','borderStyle','paddingTop','paddingRight','paddingBottom','paddingLeft','fontStyle','fontVariant','fontWeight','fontStretch','fontSize','fontSizeAdjust','lineHeight','fontFamily','textAlign','textTransform','textIndent','textDecoration','letterSpacing','wordSpacing','tabSize','MozTabSize'];var isFirefox=window.mozInnerScreenX!=null;function getCaretCoordinates(element,position,options){var debug=options&&options.debug||false;if(debug){var el=document.querySelector('#input-textarea-caret-position-mirror-div');if(el){el.parentNode.removeChild(el)}}var div=document.createElement('div');div.id='input-textarea-caret-position-mirror-div';document.body.appendChild(div);var style=div.style;var computed=window.getComputedStyle?getComputedStyle(element):element.currentStyle;style.whiteSpace='pre-wrap';if(element.nodeName!=='INPUT')style.wordWrap='break-word';style.position='absolute';if(!debug)style.visibility='hidden';properties.forEach(function(prop){style[prop]=computed[prop]});if(isFirefox){if(element.scrollHeight>parseInt(computed.height))style.overflowY='scroll'}else{style.overflow='hidden'}div.textContent=element.value.substring(0,position);if(element.nodeName==='INPUT')div.textContent=div.textContent.replace(/\s/g,"\u00a0");var span=document.createElement('span');span.textContent=element.value.substring(position)||'.';div.appendChild(span);var coordinates={top:span.offsetTop+parseInt(computed['borderTopWidth']),left:span.offsetLeft+parseInt(computed['borderLeftWidth'])};if(debug){span.style.backgroundColor='#aaa'}else{document.body.removeChild(div)}return coordinates}if(typeof module!="undefined"&&typeof module.exports!="undefined"){module.exports=getCaretCoordinates}else{window.getCaretCoordinates=getCaretCoordinates}}())}])});

代码块复制功能

依赖 clipboard.js 实现,个性化配置可参考官方文档。在 /themes/next/layout/_custom/custom.swig 引入下载的 JS

1
2
<script type="text/javascript" src="/js/src/clipboard.min.js"></script>
<script type="text/javascript" src="/js/src/clipboard-use.js"></script>

位于 /themes/next/source/js/src/ 目录下的 clipboard.min.js 和 clipboard-use.js 代码分别如下

1
2
3
4
5
6
7
/*!
* clipboard.min.js v2.0.4
* https://zenorocha.github.io/clipboard.js
*
* Licensed MIT © Zeno Rocha
*/
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return function(n){var o={};function r(t){if(o[t])return o[t].exports;var e=o[t]={i:t,l:!1,exports:{}};return n[t].call(e.exports,e,e.exports,r),e.l=!0,e.exports}return r.m=n,r.c=o,r.d=function(t,e,n){r.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},r.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.p="",r(r.s=0)}([function(t,e,n){"use strict";var r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},i=function(){function o(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}return function(t,e,n){return e&&o(t.prototype,e),n&&o(t,n),t}}(),a=o(n(1)),c=o(n(3)),u=o(n(4));function o(t){return t&&t.__esModule?t:{default:t}}var l=function(t){function o(t,e){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,o);var n=function(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e}(this,(o.__proto__||Object.getPrototypeOf(o)).call(this));return n.resolveOptions(e),n.listenClick(t),n}return function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}(o,c.default),i(o,[{key:"resolveOptions",value:function(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:{};this.action="function"==typeof t.action?t.action:this.defaultAction,this.target="function"==typeof t.target?t.target:this.defaultTarget,this.text="function"==typeof t.text?t.text:this.defaultText,this.container="object"===r(t.container)?t.container:document.body}},{key:"listenClick",value:function(t){var e=this;this.listener=(0,u.default)(t,"click",function(t){return e.onClick(t)})}},{key:"onClick",value:function(t){var e=t.delegateTarget||t.currentTarget;this.clipboardAction&&(this.clipboardAction=null),this.clipboardAction=new a.default({action:this.action(e),target:this.target(e),text:this.text(e),container:this.container,trigger:e,emitter:this})}},{key:"defaultAction",value:function(t){return s("action",t)}},{key:"defaultTarget",value:function(t){var e=s("target",t);if(e)return document.querySelector(e)}},{key:"defaultText",value:function(t){return s("text",t)}},{key:"destroy",value:function(){this.listener.destroy(),this.clipboardAction&&(this.clipboardAction.destroy(),this.clipboardAction=null)}}],[{key:"isSupported",value:function(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:["copy","cut"],e="string"==typeof t?[t]:t,n=!!document.queryCommandSupported;return e.forEach(function(t){n=n&&!!document.queryCommandSupported(t)}),n}}]),o}();function s(t,e){var n="data-clipboard-"+t;if(e.hasAttribute(n))return e.getAttribute(n)}t.exports=l},function(t,e,n){"use strict";var o,r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},i=function(){function o(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}return function(t,e,n){return e&&o(t.prototype,e),n&&o(t,n),t}}(),a=n(2),c=(o=a)&&o.__esModule?o:{default:o};var u=function(){function e(t){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,e),this.resolveOptions(t),this.initSelection()}return i(e,[{key:"resolveOptions",value:function(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:{};this.action=t.action,this.container=t.container,this.emitter=t.emitter,this.target=t.target,this.text=t.text,this.trigger=t.trigger,this.selectedText=""}},{key:"initSelection",value:function(){this.text?this.selectFake():this.target&&this.selectTarget()}},{key:"selectFake",value:function(){var t=this,e="rtl"==document.documentElement.getAttribute("dir");this.removeFake(),this.fakeHandlerCallback=function(){return t.removeFake()},this.fakeHandler=this.container.addEventListener("click",this.fakeHandlerCallback)||!0,this.fakeElem=document.createElement("textarea"),this.fakeElem.style.fontSize="12pt",this.fakeElem.style.border="0",this.fakeElem.style.padding="0",this.fakeElem.style.margin="0",this.fakeElem.style.position="absolute",this.fakeElem.style[e?"right":"left"]="-9999px";var n=window.pageYOffset||document.documentElement.scrollTop;this.fakeElem.style.top=n+"px",this.fakeElem.setAttribute("readonly",""),this.fakeElem.value=this.text,this.container.appendChild(this.fakeElem),this.selectedText=(0,c.default)(this.fakeElem),this.copyText()}},{key:"removeFake",value:function(){this.fakeHandler&&(this.container.removeEventListener("click",this.fakeHandlerCallback),this.fakeHandler=null,this.fakeHandlerCallback=null),this.fakeElem&&(this.container.removeChild(this.fakeElem),this.fakeElem=null)}},{key:"selectTarget",value:function(){this.selectedText=(0,c.default)(this.target),this.copyText()}},{key:"copyText",value:function(){var e=void 0;try{e=document.execCommand(this.action)}catch(t){e=!1}this.handleResult(e)}},{key:"handleResult",value:function(t){this.emitter.emit(t?"success":"error",{action:this.action,text:this.selectedText,trigger:this.trigger,clearSelection:this.clearSelection.bind(this)})}},{key:"clearSelection",value:function(){this.trigger&&this.trigger.focus(),window.getSelection().removeAllRanges()}},{key:"destroy",value:function(){this.removeFake()}},{key:"action",set:function(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:"copy";if(this._action=t,"copy"!==this._action&&"cut"!==this._action)throw new Error('Invalid "action" value, use either "copy" or "cut"')},get:function(){return this._action}},{key:"target",set:function(t){if(void 0!==t){if(!t||"object"!==(void 0===t?"undefined":r(t))||1!==t.nodeType)throw new Error('Invalid "target" value, use a valid Element');if("copy"===this.action&&t.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if("cut"===this.action&&(t.hasAttribute("readonly")||t.hasAttribute("disabled")))throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes');this._target=t}},get:function(){return this._target}}]),e}();t.exports=u},function(t,e){t.exports=function(t){var e;if("SELECT"===t.nodeName)t.focus(),e=t.value;else if("INPUT"===t.nodeName||"TEXTAREA"===t.nodeName){var n=t.hasAttribute("readonly");n||t.setAttribute("readonly",""),t.select(),t.setSelectionRange(0,t.value.length),n||t.removeAttribute("readonly"),e=t.value}else{t.hasAttribute("contenteditable")&&t.focus();var o=window.getSelection(),r=document.createRange();r.selectNodeContents(t),o.removeAllRanges(),o.addRange(r),e=o.toString()}return e}},function(t,e){function n(){}n.prototype={on:function(t,e,n){var o=this.e||(this.e={});return(o[t]||(o[t]=[])).push({fn:e,ctx:n}),this},once:function(t,e,n){var o=this;function r(){o.off(t,r),e.apply(n,arguments)}return r._=e,this.on(t,r,n)},emit:function(t){for(var e=[].slice.call(arguments,1),n=((this.e||(this.e={}))[t]||[]).slice(),o=0,r=n.length;o<r;o++)n[o].fn.apply(n[o].ctx,e);return this},off:function(t,e){var n=this.e||(this.e={}),o=n[t],r=[];if(o&&e)for(var i=0,a=o.length;i<a;i++)o[i].fn!==e&&o[i].fn._!==e&&r.push(o[i]);return r.length?n[t]=r:delete n[t],this}},t.exports=n},function(t,e,n){var d=n(5),h=n(6);t.exports=function(t,e,n){if(!t&&!e&&!n)throw new Error("Missing required arguments");if(!d.string(e))throw new TypeError("Second argument must be a String");if(!d.fn(n))throw new TypeError("Third argument must be a Function");if(d.node(t))return s=e,f=n,(l=t).addEventListener(s,f),{destroy:function(){l.removeEventListener(s,f)}};if(d.nodeList(t))return a=t,c=e,u=n,Array.prototype.forEach.call(a,function(t){t.addEventListener(c,u)}),{destroy:function(){Array.prototype.forEach.call(a,function(t){t.removeEventListener(c,u)})}};if(d.string(t))return o=t,r=e,i=n,h(document.body,o,r,i);throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList");var o,r,i,a,c,u,l,s,f}},function(t,n){n.node=function(t){return void 0!==t&&t instanceof HTMLElement&&1===t.nodeType},n.nodeList=function(t){var e=Object.prototype.toString.call(t);return void 0!==t&&("[object NodeList]"===e||"[object HTMLCollection]"===e)&&"length"in t&&(0===t.length||n.node(t[0]))},n.string=function(t){return"string"==typeof t||t instanceof String},n.fn=function(t){return"[object Function]"===Object.prototype.toString.call(t)}},function(t,e,n){var a=n(7);function i(t,e,n,o,r){var i=function(e,n,t,o){return function(t){t.delegateTarget=a(t.target,n),t.delegateTarget&&o.call(e,t)}}.apply(this,arguments);return t.addEventListener(n,i,r),{destroy:function(){t.removeEventListener(n,i,r)}}}t.exports=function(t,e,n,o,r){return"function"==typeof t.addEventListener?i.apply(null,arguments):"function"==typeof n?i.bind(null,document).apply(null,arguments):("string"==typeof t&&(t=document.querySelectorAll(t)),Array.prototype.map.call(t,function(t){return i(t,e,n,o,r)}))}},function(t,e){if("undefined"!=typeof Element&&!Element.prototype.matches){var n=Element.prototype;n.matches=n.matchesSelector||n.mozMatchesSelector||n.msMatchesSelector||n.oMatchesSelector||n.webkitMatchesSelector}t.exports=function(t,e){for(;t&&9!==t.nodeType;){if("function"==typeof t.matches&&t.matches(e))return t;t=t.parentNode}}}])});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/*页面载入完成后,创建复制按钮*/
!function (e, t, a) {
/* code */
var initCopyCode = function(){
var copyHtml = '';
copyHtml += '<button class="btn-copy" data-clipboard-snippet="">';
//fa fa-globe可以去字体库替换自己想要的图标
copyHtml += ' <i class="fa fa-clipboard"></i><span>复制</span>';
copyHtml += '</button>';
$(".highlight .code pre").before(copyHtml);
new ClipboardJS('.btn-copy', {
target: function(trigger) {
return trigger.nextElementSibling;
}
});
}
initCopyCode();
}(window, document);

可根据需要在 /themes/next/source/css/_custom/custom.styl 加 CSS

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
.highlight{
//position: relative;
position: static;
}
highlight-wrap {
background: #008b89;
}
.btn-copy {
display: inline-block;
cursor: pointer;
background-color: #eee;
background-image: linear-gradient(#fcfcfc,#eee);
border: 1px solid #d5d5d5;
border-radius: 3px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-appearance: none;
font-size: 13px;
font-weight: 700;
line-height: 20px;
color: #333;
-webkit-transition: opacity .3s ease-in-out;
-o-transition: opacity .3s ease-in-out;
transition: opacity .3s ease-in-out;
padding: 2px 6px;
position: absolute;
right: 5px;
top: 5px;
opacity: 0;
}
.btn-copy span {
margin-left: 5px;
}
.highlight:hover .btn-copy{
opacity: 1;
}

类知乎卡片链接

  1. 在/themes/next/source/js/src/下新建linkcard.js,内容如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
window.onload=function(){
var LinkCards=document.getElementsByClassName('LinkCard');
if(LinkCards.length != 0){
var LinkCard=LinkCards[0];
var link=LinkCard.href;
var title=LinkCard.innerText;
LinkCard.innerHTML="<style type=text/css>.LinkCard,.LinkCard:hover{text-decoration:none;border:none!important;color:inherit!important}.LinkCard{position:relative;display:block;margin:5px auto;width:330px;box-sizing:border-box;border-radius:12px;max-width:100%;overflow:hidden;color:inherit;text-decoration:none}.ztext{word-break:break-word;line-height:1.6}.LinkCard-backdrop{position:absolute;top:0;left:0;right:0;bottom:0;background-repeat:no-repeat;-webkit-filter:blur(20px);filter:blur(20px);background-size:cover;background-position:center}.LinkCard,.LinkCard:hover{text-decoration:none;border:none!important;color:inherit!important}.LinkCard-content{position:relative;display:flex;align-items:center;justify-content:space-between;padding:12px;border-radius:inherit;background-color:rgba(246,246,246,0.88)}.LinkCard-text{overflow:hidden;width:260px;}.LinkCard-title{white-space: nowrap;display:-webkit-box;-webkit-line-clamp:2;overflow:hidden;text-overflow:ellipsis;max-height:calc(16px * 1.25 * 2);font-size:16px;font-weight:500;line-height:1.25;color:#1a1a1a}@media(max-width: 767px){.LinkCard-title{font-size:13px;}}.LinkCard-meta{display:flex;margin-top:4px;font-size:14px;line-height:20px;color:#999;white-space:nowrap}.LinkCard-imageCell{margin-left:28px;border-radius:30px;width:70px;}.LinkCard-image{display:block;width:60px;height:auto;border-radius:inherit}</style><span class=LinkCard-backdrop style=background-image:url(https://zhstatic.zhihu.com/assets/zhihu/editor/zhihu-card-default.svg)></span><span class=LinkCard-content><span class=LinkCard-text><span class=LinkCard-title>"+title+"</span><span class=LinkCard-meta><span style=display:inline-flex;align-items:center><svg class="+"'Zi Zi--InsertLink'"+" fill=currentColor viewBox="+"'0 0 24 24'"+" width=17 height=17><path d="+"'M6.77 17.23c-.905-.904-.94-2.333-.08-3.193l3.059-3.06-1.192-1.19-3.059 3.058c-1.489 1.489-1.427 3.954.138 5.519s4.03 1.627 5.519.138l3.059-3.059-1.192-1.192-3.059 3.06c-.86.86-2.289.824-3.193-.08zm3.016-8.673l1.192 1.192 3.059-3.06c.86-.86 2.289-.824 3.193.08.905.905.94 2.334.08 3.194l-3.059 3.06 1.192 1.19 3.059-3.058c1.489-1.489 1.427-3.954-.138-5.519s-4.03-1.627-5.519-.138L9.786 8.557zm-1.023 6.68c.33.33.863.343 1.177.029l5.34-5.34c.314-.314.3-.846-.03-1.176-.33-.33-.862-.344-1.176-.03l-5.34 5.34c-.314.314-.3.846.03 1.177z'"+" fill-rule=evenodd></path></svg></span>"+link+"</span></span><span class=LinkCard-imageCell><img class=LinkCard-image alt=图标 src=/images/linkcard.png></span></span>";

for (var i = LinkCards.length - 1; i >= 1; i--) {
LinkCard=LinkCards[i];
title=LinkCard.innerText;
link=LinkCard.href;
LinkCard.innerHTML="<span class=LinkCard-backdrop style=background-image:url(https://zhstatic.zhihu.com/assets/zhihu/editor/zhihu-card-default.svg)></span><span class=LinkCard-content><span class=LinkCard-text><span class=LinkCard-title>"+title+"</span><span class=LinkCard-meta><span style=display:inline-flex;align-items:center><svg class="+"'Zi Zi--InsertLink'"+" fill=currentColor viewBox="+"'0 0 24 24'"+" width=17 height=17><path d="+"'M6.77 17.23c-.905-.904-.94-2.333-.08-3.193l3.059-3.06-1.192-1.19-3.059 3.058c-1.489 1.489-1.427 3.954.138 5.519s4.03 1.627 5.519.138l3.059-3.059-1.192-1.192-3.059 3.06c-.86.86-2.289.824-3.193-.08zm3.016-8.673l1.192 1.192 3.059-3.06c.86-.86 2.289-.824 3.193.08.905.905.94 2.334.08 3.194l-3.059 3.06 1.192 1.19 3.059-3.058c1.489-1.489 1.427-3.954-.138-5.519s-4.03-1.627-5.519-.138L9.786 8.557zm-1.023 6.68c.33.33.863.343 1.177.029l5.34-5.34c.314-.314.3-.846-.03-1.176-.33-.33-.862-.344-1.176-.03l-5.34 5.34c-.314.314-.3.846.03 1.177z'"+" fill-rule=evenodd></path></svg></span>"+link+"</span></span><span class=LinkCard-imageCell><img class=LinkCard-image alt=图标 src=/images/linkcard.png></span></span>";
}
}
}

需要修改/images/linkcard.png为你自己的图片。附上我在用的:linkcard.png

  1. 在/themes/next/layout/_layout.swig中body结束标签前,引入刚才新建的js:
1
<script type="text/javascript" src="/js/src/linkcard.js"></script>

使用方式:

1
<a href="https://leafjame.github.io/photos/" class="LinkCard">我的相册——时光留影</a>

效果:

我的相册——时光留影

文章评分功能

NexT主题中已经集成了widgetpack的星级评分功能,只需注册账号后,修改主题配置:

1
2
3
4
5
6
# Star rating support to each article.
# To get your ID visit https://widgetpack.com
rating:
enable: true
id: your id #<app_id>
color: ff9800

可以在widgetpack控制台中修改评分认证

KPgc3F.jpg

有三个选项,根据需要设置。

canvas粒子时钟

网上看到一款不错的canvas粒子时钟,遂整合到自己博客中来了,操作步骤:

  1. 在/themes/next/layout/_custom/目录下,新建clock.swig文件,内容如下:
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
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
<div style="">
<canvas id="canvas" style="width:60%;">当前浏览器不支持canvas,请更换浏览器后再试</canvas>
</div>
<script>
(function(){

var digit=
[
[
[0,0,1,1,1,0,0],
[0,1,1,0,1,1,0],
[1,1,0,0,0,1,1],
[1,1,0,0,0,1,1],
[1,1,0,0,0,1,1],
[1,1,0,0,0,1,1],
[1,1,0,0,0,1,1],
[1,1,0,0,0,1,1],
[0,1,1,0,1,1,0],
[0,0,1,1,1,0,0]
],//0
[
[0,0,0,1,1,0,0],
[0,1,1,1,1,0,0],
[0,0,0,1,1,0,0],
[0,0,0,1,1,0,0],
[0,0,0,1,1,0,0],
[0,0,0,1,1,0,0],
[0,0,0,1,1,0,0],
[0,0,0,1,1,0,0],
[0,0,0,1,1,0,0],
[1,1,1,1,1,1,1]
],//1
[
[0,1,1,1,1,1,0],
[1,1,0,0,0,1,1],
[0,0,0,0,0,1,1],
[0,0,0,0,1,1,0],
[0,0,0,1,1,0,0],
[0,0,1,1,0,0,0],
[0,1,1,0,0,0,0],
[1,1,0,0,0,0,0],
[1,1,0,0,0,1,1],
[1,1,1,1,1,1,1]
],//2
[
[1,1,1,1,1,1,1],
[0,0,0,0,0,1,1],
[0,0,0,0,1,1,0],
[0,0,0,1,1,0,0],
[0,0,1,1,1,0,0],
[0,0,0,0,1,1,0],
[0,0,0,0,0,1,1],
[0,0,0,0,0,1,1],
[1,1,0,0,0,1,1],
[0,1,1,1,1,1,0]
],//3
[
[0,0,0,0,1,1,0],
[0,0,0,1,1,1,0],
[0,0,1,1,1,1,0],
[0,1,1,0,1,1,0],
[1,1,0,0,1,1,0],
[1,1,1,1,1,1,1],
[0,0,0,0,1,1,0],
[0,0,0,0,1,1,0],
[0,0,0,0,1,1,0],
[0,0,0,1,1,1,1]
],//4
[
[1,1,1,1,1,1,1],
[1,1,0,0,0,0,0],
[1,1,0,0,0,0,0],
[1,1,1,1,1,1,0],
[0,0,0,0,0,1,1],
[0,0,0,0,0,1,1],
[0,0,0,0,0,1,1],
[0,0,0,0,0,1,1],
[1,1,0,0,0,1,1],
[0,1,1,1,1,1,0]
],//5
[
[0,0,0,0,1,1,0],
[0,0,1,1,0,0,0],
[0,1,1,0,0,0,0],
[1,1,0,0,0,0,0],
[1,1,0,1,1,1,0],
[1,1,0,0,0,1,1],
[1,1,0,0,0,1,1],
[1,1,0,0,0,1,1],
[1,1,0,0,0,1,1],
[0,1,1,1,1,1,0]
],//6
[
[1,1,1,1,1,1,1],
[1,1,0,0,0,1,1],
[0,0,0,0,1,1,0],
[0,0,0,0,1,1,0],
[0,0,0,1,1,0,0],
[0,0,0,1,1,0,0],
[0,0,1,1,0,0,0],
[0,0,1,1,0,0,0],
[0,0,1,1,0,0,0],
[0,0,1,1,0,0,0]
],//7
[
[0,1,1,1,1,1,0],
[1,1,0,0,0,1,1],
[1,1,0,0,0,1,1],
[1,1,0,0,0,1,1],
[0,1,1,1,1,1,0],
[1,1,0,0,0,1,1],
[1,1,0,0,0,1,1],
[1,1,0,0,0,1,1],
[1,1,0,0,0,1,1],
[0,1,1,1,1,1,0]
],//8
[
[0,1,1,1,1,1,0],
[1,1,0,0,0,1,1],
[1,1,0,0,0,1,1],
[1,1,0,0,0,1,1],
[0,1,1,1,0,1,1],
[0,0,0,0,0,1,1],
[0,0,0,0,0,1,1],
[0,0,0,0,1,1,0],
[0,0,0,1,1,0,0],
[0,1,1,0,0,0,0]
],//9
[
[0,0,0,0,0,0,0],
[0,0,1,1,1,0,0],
[0,0,1,1,1,0,0],
[0,0,1,1,1,0,0],
[0,0,0,0,0,0,0],
[0,0,0,0,0,0,0],
[0,0,1,1,1,0,0],
[0,0,1,1,1,0,0],
[0,0,1,1,1,0,0],
[0,0,0,0,0,0,0]
]//:
];

var canvas = document.getElementById('canvas');

if(canvas.getContext){
var cxt = canvas.getContext('2d');
//声明canvas的宽高
var H = 100,W = 700;
canvas.height = H;
canvas.width = W;
cxt.fillStyle = '#f00';
cxt.fillRect(10,10,50,50);

//存储时间数据
var data = [];
//存储运动的小球
var balls = [];
//设置粒子半径
var R = canvas.height/20-1;
(function(){
var temp = /(\d)(\d):(\d)(\d):(\d)(\d)/.exec(new Date());
//存储时间数字,由十位小时、个位小时、冒号、十位分钟、个位分钟、冒号、十位秒钟、个位秒钟这7个数字组成
data.push(temp[1],temp[2],10,temp[3],temp[4],10,temp[5],temp[6]);
})();

/*生成点阵数字*/
function renderDigit(index,num){
for(var i = 0; i < digit[num].length; i++){
for(var j = 0; j < digit[num][i].length; j++){
if(digit[num][i][j] == 1){
cxt.beginPath();
cxt.arc(14*(R+2)*index + j*2*(R+1)+(R+1),i*2*(R+1)+(R+1),R,0,2*Math.PI);
cxt.closePath();
cxt.fill();
}
}
}
}

/*更新时钟*/
function updateDigitTime(){
var changeNumArray = [];
var temp = /(\d)(\d):(\d)(\d):(\d)(\d)/.exec(new Date());
var NewData = [];
NewData.push(temp[1],temp[2],10,temp[3],temp[4],10,temp[5],temp[6]);
for(var i = data.length-1; i >=0 ; i--){
//时间发生变化
if(NewData[i] !== data[i]){
//将变化的数字值和在data数组中的索引存储在changeNumArray数组中
changeNumArray.push(i+'_'+(Number(data[i])+1)%10);
}
}
//增加小球
for(var i = 0; i< changeNumArray.length; i++){
addBalls.apply(this,changeNumArray[i].split('_'));
}
data = NewData.concat();
}

/*更新小球状态*/
function updateBalls(){
for(var i = 0; i < balls.length; i++){
balls[i].stepY += balls[i].disY;
balls[i].x += balls[i].stepX;
balls[i].y += balls[i].stepY;
if(balls[i].x > W + R || balls[i].y > H + R){
balls.splice(i,1);
i--;
}
}
}

/*增加要运动的小球*/
function addBalls(index,num){
var numArray = [1,2,3];
var colorArray = ["#3BE","#09C","#A6C","#93C","#9C0","#690","#FB3","#F80","#F44","#C00"];
for(var i = 0; i < digit[num].length; i++){
for(var j = 0; j < digit[num][i].length; j++){
if(digit[num][i][j] == 1){
var ball = {
x:14*(R+2)*index + j*2*(R+1)+(R+1),
y:i*2*(R+1)+(R+1),
stepX:Math.floor(Math.random() * 4 -2),
stepY:-2*numArray[Math.floor(Math.random()*numArray.length)],
color:colorArray[Math.floor(Math.random()*colorArray.length)],
disY:1
};
balls.push(ball);
}
}
}
}

/*渲染*/
function render(){
//重置画布宽度,达到清空画布的效果
canvas.height = 100;
//渲染时钟
for(var i = 0; i < data.length; i++){
renderDigit(i,data[i]);
}
//渲染小球
for(var i = 0; i < balls.length; i++){
cxt.beginPath();
cxt.arc(balls[i].x,balls[i].y,R,0,2*Math.PI);
cxt.fillStyle = balls[i].color;
cxt.closePath();
cxt.fill();
}
}

clearInterval(oTimer);
var oTimer = setInterval(function(){
//更新时钟
updateDigitTime();
//更新小球状态
updateBalls();
//渲染
render();
},50);
}

})();
</script>
  1. 在/themes/next/layout/_macro/sidebar.swig中引入:
1
{% include '../_custom/clock.swig' %}

可根据自己的偏好来设置具体位置,我是加在了侧栏的末尾:

uiJDPJ.gif

另一款样式可参考:

HTML5 Canvas实现会跳舞的时间动画

网站运行时间

  1. 在/themes/next/layout/_custom/下新建runtime.swig,拷贝如下内容:
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
<div id="days"></div>
</script>
<script language="javascript">
function show_date_time(){
window.setTimeout("show_date_time()", 1000);
BirthDay=new Date("08/07/2019 20:00:00");
today=new Date();
timeold=(today.getTime()-BirthDay.getTime());
sectimeold=timeold/1000
secondsold=Math.floor(sectimeold);
msPerDay=24*60*60*1000
e_daysold=timeold/msPerDay
daysold=Math.floor(e_daysold);
e_hrsold=(e_daysold-daysold)*24;
hrsold=setzero(Math.floor(e_hrsold));
e_minsold=(e_hrsold-hrsold)*60;
minsold=setzero(Math.floor((e_hrsold-hrsold)*60));
seconds=setzero(Math.floor((e_minsold-minsold)*60));
document.getElementById('days').innerHTML="已运行"+daysold+"天"+hrsold+"时"+minsold+"分"+seconds+"秒";
}
function setzero(i){
if (i<10)
{i="0" + i};
return i;
}
show_date_time();
</script>

修改BirthDay为你建站的时间

  1. 在/themes/next/layout/_macro/sidebar.swig中引入:
1
{% include '../_custom/runtime.swig' %}

网站动态背景图片

在 /themes/next/source/css/_custom/custom.styl 中设置 body 属性

1
2
3
4
5
6
body {
background:url(https://source.unsplash.com/random/1600x900);
background-repeat: no-repeat;
background-attachment:fixed;
background-position:50% 50%;
}

其中的 url 可根据 Unsplash Source 这个网站来生成,比如随机选择、根据指定用户选择等等,效果:

KPrR8H.jpg

其它的背景点击特效—波浪、线条、水纹波动等,可以在主题 _config.yml 中 canvas 系列进行设置,如 canvas_nest、canvas_ribbon。 motion 配置项则是设置诸如侧栏、文章标题的加载动画。

网站 logo 炫彩效果

PC 端只显示在左上角 logo 位置,移动端效果如下

移动端效果

我使用的是 NexT 5 的 Pisces(主题 _config.yml 中 scheme 配置),主要设置样式为 site-meta,其它的主题类型需要自己调整。在 /themes/next/source/css/_custom/custom.styl 中添加以下 css ,如果之前已经设置了,根据情况进行替换:

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
.site-title{
background-image: linear-gradient(
to right,
orangered,
orange,
gold,
lightgreen,
cyan,
dodgerblue,
mediumpurple,
hotpink,
orangered
);
background-size: 110vw;
-webkit-background-clip: text;
color: rgba(0,0,0,0.1); /* transparent IE 不支持 */
animation: sliding 30s linear infinite;
}
@keyframes sliding{
to{
background-position: -2000vw;
}
}

.site-meta,
.site-subtitle {
color: rgba(0,0,0,0.1); /* transparent IE 不支持 */
animation: hue 1.5s linear infinite;
background-image: linear-gradient(to right bottom, rgb(255,0,0), rgb(255,128,0), rgb(255,255,0), rgb(0,255,0), rgb(0,255,128), rgb(0,255,255), rgb(0,128,255), rgb(0,0,255), rgb(128,0,255), rgb(255,0,255), rgb(255,0,128));
-webkit-background-clip: text;
}
@keyframes hue {
from {
filter: hue-rotate(0);
}
to {
filter: hue-rotate(-360deg);
}
}

.site-meta{
background: #ecf9f8;
+mobile(){
padding: 10px 0;
background-image: linear-gradient(90deg,#f79533 0,#f37055 15%,#ef4e7b 30%,#a166ab 44%,#5073b8 58%,#1098ad 72%,#07b39b 86%,#6dba82 100%)!important;
}
}

其它炫彩字体效果可参考:

CSS 3 立体文字最佳实践

旋转魔方(个性化返回顶部)

效果 1 :

K9t8nH.gif

效果 2 :

K9tGBd.gif

之前回到顶部功能使用的是一张图片,大屏幕下计算会有问题,然后自己就在魔方里加了个方法来实现,正好移动端也能用。

KP2qiV.jpg

说一下这个猫的配置吧,给有需要的朋友。只需在 /themes/next/source/css/_custom/custom.styl 添加如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.back-to-top {
//right: 60px;
width: 70px; //图片素材宽度
height: 900px; //图片素材高度
top: -900px;
bottom: unset;
transition: all .5s ease-in-out;
background: url("/images/scroll.png");
//隐藏箭头图标
> i {
display: none;
}
&.back-to-top-on {
bottom: unset;
top: 100vh < (900px + 200px) ? calc( 100vh - 900px - 200px ) : 0px;
}
}

然后修改 background 里的 url 为图片地址。 下载图片 保存为 scroll.png 放到 /themes/next/source/images/ 目录即可。

魔方一

100素材网 看到的,自己修改了下大小就放博客里来了。在 /themes/next/layout/_custom/ 下新建 cube-mini.swig(名字随便吧 -.- ),内容如下:

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
<style>
.cube_container {
width: 50px;
height: 60px;
margin: 0 auto;
position: fixed;
z-index: 999;
-webkit-perspective: 1000px;
perspective: 1000px;
right: 0px;
bottom: 0px;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}

.cube {
/*
width: 100%;
height: 100%;
*/
width: 0%; /* 大角度旋转 */
position: absolute;
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-transform: rotateX(-15deg) rotateY(-20deg) translateZ(-100px);
transform: rotateX(-15deg) rotateY(-20deg) translateZ(-100px);
-webkit-transform-origin: center center -100px;
transform-origin: center center -100px;
-webkit-animation: around 5s cubic-bezier(0.94, -0.6, 0.45, 1.31) infinite;
animation: around 5s cubic-bezier(0.94, -0.6, 0.45, 1.31) infinite;
}
.cube div {
width: 50px;
height: 50px;
display: block;
margin: 0;
position: absolute;
}
.cube div a {
color: white;
font-size: 12px;
text-decoration: none;
text-align: center;
position: fixed;
top: 50%;
left: 45%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
.cube .front {
-webkit-transform: rotateY(0deg) translateZ(25px);
transform: rotateY(0deg) translateZ(25px);
background-color: rgba(0, 191, 255, 0.7);
border: 1px solid rgba(0, 191, 255, 0.7);
}
.cube .back {
-webkit-transform: rotateX(180deg) translateZ(25px);
transform: rotateX(180deg) translateZ(25px);
background-color: rgba(124, 252, 0, 0.7);
border: 1px solid rgba(124, 252, 0, 0.7);
}
.cube .left {
-webkit-transform: rotateY(-90deg) translateZ(25px);
transform: rotateY(-90deg) translateZ(25px);
background-color: rgba(255, 215, 0, 0.7);
border: 1px solid rgba(255, 215, 0, 0.7);
}
.cube .right {
-webkit-transform: rotateY(90deg) translateZ(25px);
transform: rotateY(90deg) translateZ(25px);
background-color: rgba(255, 69, 0, 0.7);
border: 1px solid rgba(255, 69, 0, 0.7);
}
.cube .top {
-webkit-transform: rotateX(90deg) translateZ(25px);
transform: rotateX(90deg) translateZ(25px);
background-color: rgba(255, 0, 157, 0.7);
border: 1px solid rgba(255, 0, 157, 0.7);
}
.cube .bottom {
-webkit-transform: rotateX(-90deg) translateZ(25px);
transform: rotateX(-90deg) translateZ(25px);
background-color: rgba(184, 111, 220, 0.7);
border: 1px solid rgba(184, 111, 220, 0.7);
}

@-webkit-keyframes around {
100% {
-webkit-transform: rotateX(-15deg) rotateY(-380deg) translateZ(-100px);
transform: rotateX(-15deg) rotateY(-380deg) translateZ(-100px);
}
}

@keyframes around {
100% {
-webkit-transform: rotateX(-15deg) rotateY(-380deg) translateZ(-100px);
transform: rotateX(-15deg) rotateY(-380deg) translateZ(-100px);
}
}
</style>

<div class="cube_container">
<div class="cube">
<div class="front"><a onclick="back2top()" rel="nofollow"> 欢迎光临 </a></div>
<div class="back"><a onclick="back2top()" rel="nofollow"> ❤️ </a></div>
<div class="right"><a onclick="back2top()" rel="nofollow"> 北宸小站 </a></div>
<div class="left"><a onclick="back2top()" role="button" rel="nofollow"> 请多关照 </a></div>
<div class="top"><a href="https://github.com/leafjame/hexo-theme-next5-leaf" target="_blank" rel="nofollow"> ❤️ </a></div>
<div class="bottom"><a href="https://github.com/leafjame/hexo-theme-next5-leaf" target="_blank" rel="nofollow"> ❤️ </a></div>
</div>
</div>

<script>
function back2top(){
$('html, body').animate({scrollTop: 0}, 500);
}
</script>

当然,也可以直接扒100素材网的样式再修改。

魔方二

样式来自 FEWY的博客,初始时魔方比较大,我已调整。在 /themes/next/layout/_custom/ 下新建 cube-hollow.swig,内容如下:

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
<style>
/*最外层容器样式*/
.wrap {
width: 0px;
height: 0px;
/*margin: 80px;*/
/*position: relative;*/
position: fixed;
bottom: 120px;
right: 80px;
z-index: 999;
}

/*包裹所有容器样式*/
.cube {
width: 0px;
height: 0px;
margin: 0 auto;
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
transform: rotateX(-30deg) rotateY(-80deg);
animation: rotate linear 10s infinite;
}

@-webkit-keyframes rotate {
from {
transform: rotateX(0deg) rotateY(0deg);
}
to {
transform: rotateX(360deg) rotateY(360deg);
}
}

.cube div {
position: absolute;
width: 50px;
height: 50px;
opacity: 0.8;
transition: all .4s;
}

/*定义所有图片样式*/
.pic {
width: 50px;
height: 50px;
}

.cube .out_front {
transform: rotateY(0deg) translateZ(25px);
}

.cube .out_back {
transform: translateZ(-25px) rotateY(180deg);
}

.cube .out_left {
transform: rotateY(-90deg) translateZ(25px);
}

.cube .out_right {
transform: rotateY(90deg) translateZ(25px);
}

.cube .out_top {
transform: rotateX(90deg) translateZ(25px);
}

.cube .out_bottom {
transform: rotateX(-90deg) translateZ(25px);
}

/*定义小正方体样式*/
.cube span {
display: block;
width: 25px;
height: 25px;
position: absolute;
top: 12px;
left: 12px;
}

.cube .in_pic {
width: 25px;
height:25px;
}

.cube .in_front {
transform: rotateY(0deg) translateZ(12px);
}

.cube .in_back {
transform: translateZ(-12px) rotateY(180deg);
}

.cube .in_left {
transform: rotateY(-90deg) translateZ(12px);
}

.cube .in_right {
transform: rotateY(90deg) translateZ(12px);
}

.cube .in_top {
transform: rotateX(90deg) translateZ(12px);
}

.cube .in_bottom {
transform: rotateX(-90deg) translateZ(12px);
}

/*鼠标移入后样式*/
.cube:hover .out_front {
transform: rotateY(0deg) translateZ(50px);
}

.cube:hover .out_back {
transform: translateZ(-50px) rotateY(180deg);
}

.cube:hover .out_left {
transform: rotateY(-90deg) translateZ(50px);
}

.cube:hover .out_right {
transform: rotateY(90deg) translateZ(50px);
}

.cube:hover .out_top {
transform: rotateX(90deg) translateZ(50px);
}

.cube:hover .out_bottom {
transform: rotateX(-90deg) translateZ(50px);
}
</style>

<div class="wrap">

<!--包裹所有元素的容器-->
<div class="cube">
<!--前面图片 -->
<div class="out_front">
<a onclick="back2top()">
<img src="https://s2.ax1x.com/2019/10/14/KpEBJx.th.jpg" class="pic" />
</a>
</div>
<!--后面图片 -->
<div class="out_back">
<a onclick="back2top()">
<img src="https://s2.ax1x.com/2019/10/14/KpEBJx.th.jpg" class="pic" />
</a>
</div>
<!--左面图片 -->
<div class="out_left">
<a onclick="back2top()">
<img src="https://s2.ax1x.com/2019/10/14/KpEBJx.th.jpg" class="pic" />
</a>
</div>
<!--右面图片 -->
<div class="out_right">
<a onclick="back2top()">
<img src="https://s2.ax1x.com/2019/10/14/KpEBJx.th.jpg" class="pic" />
</a>
</div>
<!--上面图片 -->
<div class="out_top">
<a onclick="back2top()">
<img src="https://s2.ax1x.com/2019/10/14/KpEBJx.th.jpg" class="pic" />
</a>
</div>
<!--下面图片 -->
<div class="out_bottom">
<a onclick="back2top()">
<img src="https://s2.ax1x.com/2019/10/14/KpEBJx.th.jpg" class="pic" />
</a>
</div>

<!--小正方体 -->
<span class="in_front">
<img src="https://s2.ax1x.com/2019/10/14/KptCPf.th.jpg" class="in_pic" />
</span>
<span class="in_back">
<img src="https://s2.ax1x.com/2019/10/14/KptCPf.th.jpg" class="in_pic" />
</span>
<span class="in_left">
<img src="https://s2.ax1x.com/2019/10/14/KptCPf.th.jpg" class="in_pic" />
</span>
<span class="in_right">
<img src="https://s2.ax1x.com/2019/10/14/KptCPf.th.jpg" class="in_pic" />
</span>
<span class="in_top">
<img src="https://s2.ax1x.com/2019/10/14/KptCPf.th.jpg" class="in_pic" />
</span>
<span class="in_bottom">
<img src="https://s2.ax1x.com/2019/10/14/KptCPf.th.jpg" class="in_pic" />
</span>
</div>

</div>

<script>
function back2top(){
$('html, body').animate({scrollTop: 0}, 500);
}
</script>
引用
  1. 在 /themes/next/layout/_custom/custom.swig 中引入新建的文件
1
2
3
4
5
6
7
8
<!-- 旋转魔方 -->
{% if theme.cube.enable %}
{% if theme.cube.type == "mini" %}
{% include 'cube-mini.swig' %}
{% elseif theme.cube.type == "hollow" %}
{% include 'cube-hollow.swig' %}
{% endif %}
{% endif %}
  1. 在主题 _config.yml 中新建以下动态配置项
1
2
3
cube:
enable: true
type: hollow # mini | hollow

图片链接替换成你自己的,hexo 三连,移动端也有效果了,enjoy!

一些建议

图片压缩

可以使用 WebP 格式 的图片替代 JPG、PNG 等,比如这样: 示例图片,在 Chrome 和 FireFox 都正常,IE 和 Safari 目前还不兼容,毕竟是谷歌推出的技术。我们也可通过修改 hexo 代码,增加 webp 图片支持,比如 这篇文章,不过也有点麻烦 -.-!

下边推荐一个不错的网站,在线 JPG to WebP,再 WebP to JPG,图片就会被压缩,支持 GIF 、Video 等多种格式转换。

Online GIF maker and image editor

比如我上传本地 JPG 图片,下方显示:

1
File size: 509.99KiB, width: 1182px, height: 1182px, type: png

转换成 webp 后,大小仅有 26 kb 左右,即上边的示例图片:

1
File size: 26.34KiB (-94.84%), width: 1182px, height: 1182px, frames: 1, type: webp

拷贝转换后的 webp 图片地址,再选择 WebP to JPG 选项,粘贴进输入框,upload 后,在 image quality factor、Background color 默认情况下,转回 JPG :

1
File size: 59.33KiB (+125.26%), width: 1182px, height: 1182px, type: jpg

相比 webp,图片又变大了,但相比原图,却是小了很多,压缩了好几倍,清晰度没什么太大变化。部分图片压缩效果可能没那么理想,比如本身就不大的图片,有时候反而还压大了。转 PNG 图片会大一些,可先转为 JPG,对清晰度要求不高的,可以尝试多转换几次。

点击查看

本文标题:Hexo NexT主题美化2.0

文章作者:北宸

发布时间:2019年09月21日 - 15:55:24

最后更新:2019年10月15日 - 23:38:29

原始链接:https://leafjame.github.io/posts/2114475547.html

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

-------------------本文结束 感谢您的阅读-------------------