想法来自 Vino 大佬的博客,我觉得使用一个 Loading 页面来缓解博客渲染速度慢带来的尴尬是件酷酷的事情。自己捣鼓了一下如何把任何一个页面改成 Hexo 博客下的 Loading 页面,发现其实还是比较简单的。
下面我来说一下我魔改的具体步骤。
一、制作 Loading 页面
- 首先我们需要准备一个已经写好的 Loading 动画页面。
 (这种动画页面网上有很多大佬提供了开源项目,咋就不重复造轮子了,嘿嘿~)
我这里以大佬 YanH 写的 Loading 动画页面为例。
其页面具体代码如下:
| 12
 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
 
 | <!DOCTYPE html><html>
 
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
 
 <title>带LOGO的全屏加载动画</title>
 <link rel="stylesheet" href="118.css">
 </head>
 
 <body>
 <div class="loader-wrapper">
 <div class="loader"><img src="/images/1.png" alt=""></div>
 <div class="loader-text">
 
 <div>L</div>
 <div>O</div>
 <div>A</div>
 <div>D</div>
 <div>I</div>
 <div>N</div>
 <div>G</div>
 <div></div>
 <div></div>
 <div></div>
 </div>
 </div>
 </body>
 
 </html>
 
 | 
| 12
 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
 
 | *{
 margin: 0;
 padding: 0;
 }
 body{
 
 height: 100vh;
 }
 .loader-wrapper{
 
 position: fixed;
 left: 0;
 top: 0;
 z-index: 1;
 width: 100%;
 height: 100%;
 
 overflow: hidden;
 
 background: linear-gradient(45deg,rgb(90,54,148) 0%,rgb(19,189,206) 33%,rgb(0,148,217) 66%,rgb(111,199,181) 100%);
 background-size: 400%;
 background-position: 0% 100%;
 
 animation: gradient 7.5s ease-in-out infinite;
 }
 
 .loader{
 width: 150px;
 height: 150px;
 border: 3px solid transparent;
 border-top-color: #fff;
 
 position: relative;
 left: 50%;
 top: 50%;
 margin-left: -75px;
 margin-top: -75px;
 z-index: 2;
 border-radius: 50%;
 display: flex;
 justify-content: center;
 align-items: center;
 
 animation: spin 1.7s linear infinite;
 }
 
 .loader::before{
 content: "";
 
 position: absolute;
 top: 5px;
 left: 5px;
 bottom: 5px;
 right: 5px;
 border-radius: 50%;
 border: 3px solid transparent;
 border-top-color: #fff;
 
 animation: spin 0.6s linear infinite reverse;
 }
 
 .loader::after{
 content: "";
 
 position: absolute;
 top: 15px;
 left: 15px;
 bottom: 15px;
 right: 15px;
 border-radius: 50%;
 border: 3px solid transparent;
 border-top-color: #fff;
 
 animation: spin 1s linear infinite;
 }
 
 .loader img{
 width: 55%;
 height: 55%;
 border-radius: 50%;
 
 animation: spin 1.7s linear infinite reverse;
 }
 .loader-text{
 width: 50%;
 height: 36px;
 
 position: absolute;
 top: 72%;
 left: 50%;
 transform: translateX(-50%);
 z-index: 3;
 
 user-select: none;
 }
 .loader-text div{
 width: 30px;
 height: 36px;
 color: #fff;
 font-size: 32px;
 margin: 0 20px;
 
 position: absolute;
 
 opacity: 0;
 transform: rotate(180deg);
 
 animation: move 2s linear infinite;
 }
 
 .loader-text div:nth-child(8)::before,
 .loader-text div:nth-child(9)::before,
 .loader-text div:nth-child(10)::before{
 content: "";
 width: 10px;
 height: 10px;
 border-radius: 50%;
 background-color: #fff;
 position: absolute;
 left: 0;
 bottom: 0;
 }
 
 .loader-text div::after{
 content: "";
 width: 10px;
 height: 5px;
 border-radius: 50%;
 background-color: rgba(255,255,255,0.15);
 position: absolute;
 bottom: -40px;
 left: 50%;
 margin-left: -5px;
 }
 
 .loader-text div:nth-child(8)::after,
 .loader-text div:nth-child(9)::after,
 .loader-text div:nth-child(10)::after{
 left: 0;
 margin-left: 0;
 }
 
 .loader-text div:nth-child(2){
 animation-delay: 0.2s;
 }
 .loader-text div:nth-child(3){
 animation-delay: 0.4s;
 }
 .loader-text div:nth-child(4){
 animation-delay: 0.6s;
 }
 .loader-text div:nth-child(5){
 animation-delay: 0.8s;
 }
 .loader-text div:nth-child(6){
 animation-delay: 1s;
 }
 .loader-text div:nth-child(7){
 animation-delay: 1.2s;
 }
 .loader-text div:nth-child(8){
 animation-delay: 1.4s;
 }
 .loader-text div:nth-child(9){
 animation-delay: 1.6s;
 }
 .loader-text div:nth-child(10){
 animation-delay: 1.8s;
 }
 
 
 
 @keyframes gradient {
 50%{
 background-position: 100% 0%;
 }
 }
 
 @keyframes spin {
 0%{
 transform: rotate(0);
 }
 100%{
 transform: rotate(360deg);
 }
 }
 
 @keyframes move {
 0%{
 right: 0;
 opacity: 0;
 }
 35%{
 right: 41%;
 opacity: 1;
 transform: rotate(0);
 }
 65%{
 right: 59%;
 opacity: 1;
 transform: rotate(0);
 }
 100%{
 right: 100%;
 transform: rotate(-180deg);
 }
 }
 
 | 
- 适配手机样式。一定要注意手机样式是否显示正常,如果不正常可以通过如下代码进行重新调整。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 
 | @media only screen and (max-width: 601px) {
 
 }
 
 @media only screen and (min-width: 600px) and (max-width: 992px) {
 
 }
 
 @media only screen and (min-width: 993px) {
 
 }
 
 | 
- 最后注意调整 Loading 页面层级,使其在所有页面的最上面。
| 12
 3
 
 | .loader-wrapper {z-index: 10000;
 }
 
 | 
二、引入自己的博客
修改好了 Loading 动画页面后就可以引入自己的博客中了。
- 首先,在主题文件夹中的 \layout\_widget\文件夹里创建一个loading.ejs文件。

- 用编辑器打开该文件,写入以下代码。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 
 | <% if (theme.preloader.enable) { %><div id="loader-box">
 /* 你的 HTML 代码将放在这里 */
 
 <script>
 var endLoading = function () {
 document.body.style.overflow = 'auto';
 document.getElementById('loader-box').remove();
 }
 window.addEventListener('load',endLoading);
 </script>
 </div>
 <% } %>
 
 | 
- 打开准备的 Loading 动画 HTML 文件,将 <body> 标签下的所有内容复制到第 2 步注释标注的位置。

- 在主题目录下的 source文件夹里找到css文件夹,新建一个loading.css文件,并将前面修改好的 CSS 文件内容复制进去、保存。

- 然后打开主题目录下的 _config.yml文件,添加如下代码,增加一个控制 Loading 页面的开关。
| 12
 3
 
 | preloader:
 enable: true
 
 | 
- 接着在主题目录下的 _config.yml找到libs的配置项,在css子项里添加自己的 loading.css 文件位置信息。参考代码如下。
| 12
 3
 
 | libs:css:
 loadingPage: /css/loading.css
 
 | 
- 紧接着我们就可以在页面中引用相关文件了。
- 打开 layout\_partial\head.ejs文件,在 <head> 标签里添加代码:
| 12
 3
 4
 
 | <% if (theme.preloader.enable) { %>
 <link rel="stylesheet" type="text/css" href="<%- theme.jsDelivr.url %><%- theme.libs.css.loadingPage %>">
 <% } %>
 
 | 
- 最后我们打开 layout\layout.ejs文件,在 <body> 标签下最前的位置添加代码:
| 12
 3
 4
 
 | <% if (theme.preloader.enable) { %>
 <%- partial('_widget/loading') %>
 <% } %>
 
 | 
三、部署
hexo cl && hexo g && hexo d 一键三连即可。具体一些细节需要根据自己的需求自己修改解决,这里只提供一个自定义 Loading 页面的大体思路,希望大家能自己思考,做出自己风格的独特 Blog,嘿嘿(●ˇ∀ˇ●)~
溜了~
四、【更新】优化判断算法
这个嘛,前面给的算法写在 loading.ejs 里是为了代码模块化,尽量相关的代码都写在一起。
之前的算法| 12
 3
 4
 5
 6
 7
 
 | <script>var endLoading = function () {
 document.body.style.overflow = 'auto';
 document.getElementById('loader-box').remove();
 }
 window.addEventListener('load',endLoading);
 </script>
 
 | 
 所以,最开始提供的算法是通过监听 ‘load’ 时间来完成的,也就是说 Loading 页面必须是在当前页面中所有资源都加载完毕后才关闭的。
这样一来,就会产生一个小问题:我们希望 Loading 页面是在我们可见资源(也就是页面显示的内容)都加载完毕后就立刻关闭,而不是还要等一些无关紧要的东西加载完毕才关闭。
那么,为了优化这一点,我们必须在之前的代码上做点小改动!(因为我有懒图加载,所有 Loading 页面不会被图片加载阻塞)
- 首先,将之前的算法代码删除;
- 来到主题目录里的 layout.ejs文件,在 <body> 标签的最后位置添加如下代码:
服务器慢的(注意添加位置)| 12
 3
 
 | <script id="removeLoading">document.getElementById('loader-box').remove();
 </script>
 
 | 
 - 然后给不必要的 JS 脚本(自己判断)加上 async 或 defer 属性。【相关知识请看此文章】
注意一个细节:
如果你的服务器非常给力,页面全部资源的加载速度可以达到 1s 以内的话建议不要这么做。因为你的 Loading 页面会一闪而过,甚至看不清楚是什么东西。
建议访问速度特别快的在原方法里做些小改动即可:
服务器给力的| 12
 3
 4
 5
 6
 7
 8
 
 | var endLoading = function () {document.body.style.overflow = 'auto';
 
 setTimeout(function(){
 document.getElementById('loader-box').remove();
 }, 1000  );
 }
 window.addEventListener('load',endLoading);
 
 |