想法来自 Vino 大佬的博客,我觉得使用一个 Loading 页面来缓解博客渲染速度慢带来的尴尬是件酷酷的事情。自己捣鼓了一下如何把任何一个页面改成 Hexo 博客下的 Loading 页面,发现其实还是比较简单的。
下面我来说一下我魔改的具体步骤。
一、制作 Loading 页面
- 首先我们需要准备一个已经写好的 Loading 动画页面。
(这种动画页面网上有很多大佬提供了开源项目,咋就不重复造轮子了,嘿嘿~)
我这里以大佬 YanH 写的 Loading 动画页面为例。
其页面具体代码如下:
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
| <!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>
|
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
| *{ 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); } }
|
- 适配手机样式。一定要注意手机样式是否显示正常,如果不正常可以通过如下代码进行重新调整。
1 2 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 页面层级,使其在所有页面的最上面。
1 2 3
| .loader-wrapper { z-index: 10000; }
|
二、引入自己的博客
修改好了 Loading 动画页面后就可以引入自己的博客中了。
- 首先,在主题文件夹中的
\layout\_widget\
文件夹里创建一个 loading.ejs
文件。
- 用编辑器打开该文件,写入以下代码。
1 2 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 页面的开关。
1 2 3
| preloader: enable: true
|
- 接着在主题目录下的
_config.yml
找到 libs
的配置项,在 css
子项里添加自己的 loading.css 文件位置信息。参考代码如下。
1 2 3
| libs: css: loadingPage: /css/loading.css
|
- 紧接着我们就可以在页面中引用相关文件了。
- 打开
layout\_partial\head.ejs
文件,在 <head> 标签里添加代码:
1 2 3 4
| <% if (theme.preloader.enable) { %> <link rel="stylesheet" type="text/css" href="<%- theme.jsDelivr.url %><%- theme.libs.css.loadingPage %>"> <% } %>
|
- 最后我们打开
layout\layout.ejs
文件,在 <body> 标签下最前的位置添加代码:
1 2 3 4
| <% if (theme.preloader.enable) { %> <%- partial('_widget/loading') %> <% } %>
|
三、部署
hexo cl && hexo g && hexo d
一键三连即可。具体一些细节需要根据自己的需求自己修改解决,这里只提供一个自定义 Loading 页面的大体思路,希望大家能自己思考,做出自己风格的独特 Blog,嘿嘿(●ˇ∀ˇ●)~
溜了~
四、【更新】优化判断算法
这个嘛,前面给的算法写在 loading.ejs
里是为了代码模块化,尽量相关的代码都写在一起。
之前的算法1 2 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> 标签的最后位置添加如下代码:
服务器慢的(注意添加位置)1 2 3
| <script id="removeLoading"> document.getElementById('loader-box').remove(); </script>
|
- 然后给不必要的 JS 脚本(自己判断)加上 async 或 defer 属性。【相关知识请看此文章】
注意一个细节:
如果你的服务器非常给力,页面全部资源的加载速度可以达到 1s 以内的话建议不要这么做。因为你的 Loading 页面会一闪而过,甚至看不清楚是什么东西。
建议访问速度特别快的在原方法里做些小改动即可:
服务器给力的1 2 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);
|