最近把首页的顶图配置启用了,为了加一张背景图整个博客的加载速度都受到了影响,不仅访问体验不流畅,甚至一点都不美观(特别是图片资源卡住的时候)。尝试找了一圈,最终找到了一个调整图片加载的方案比较贴近我的需求。按照原文章提供的部分代码做出调整,适配了pjax以及增加了手机端的设备判断,最终得出了本博客使用的效果。
样式预览
原理是先加载小图文件并进行高斯模糊处理,在大图加载完成后再对大图进行加载。
操作步骤
以本站使用的主题anzhiyu
为例(butterfly通用),为首页顶部图配置渐进式加载。这个方法应该也同样适用于一图流的博客背景,有需要的朋友可以自己研究一下~
1、新建文件
- 新建文件
source/js/imgloaded.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
|
class ProgressiveLoad { constructor(smallSrc, largeSrc) { this.smallSrc = smallSrc; this.largeSrc = largeSrc; this.initTpl(); }
initTpl() { this.container = document.createElement('div'); this.smallStage = document.createElement('div'); this.largeStage = document.createElement('div'); this.smallImg = new Image(); this.largeImg = new Image(); this.container.className = 'pl-container'; this.smallStage.className = 'pl-img pl-blur'; this.largeStage.className = 'pl-img'; this.container.appendChild(this.smallStage); this.container.appendChild(this.largeStage); this.smallImg.onload = this._onSmallLoaded.bind(this); this.largeImg.onload = this._onLargeLoaded.bind(this); }
progressiveLoad() { this.smallImg.src = this.smallSrc; this.largeImg.src = this.largeSrc; }
_onLargeLoaded() { this.largeStage.classList.add('pl-visible'); this.largeStage.style.backgroundImage = `url('${this.largeSrc}')`; }
_onSmallLoaded() { this.smallStage.classList.add('pl-visible'); this.smallStage.style.backgroundImage = `url('${this.smallSrc}')`; } } const executeLoad = (config, target) => { console.log('执行渐进背景替换'); const isMobile = window.matchMedia('(max-width: 767px)').matches; const loader = new ProgressiveLoad( isMobile ? config.mobileSmallSrc : config.smallSrc, isMobile ? config.mobileLargeSrc : config.largeSrc ); if (target.children[0]) { target.insertBefore(loader.container, target.children[0]); } loader.progressiveLoad(); }; const config = { smallSrc: '/img/xiaotu.jpg', largeSrc: '/img/tu.jpg', mobileSmallSrc: '/img/sjxt.jpg', mobileLargeSrc: '/img/sjdt.jpg', enableRoutes: ['/'], };
function initProgressiveLoad(config) { const target = document.getElementById('page-header'); if (target && target.classList.contains('full_page')) { executeLoad(config, target); } } function onPJAXComplete(config) { const target = document.getElementById('page-header'); if (target && target.classList.contains('full_page')) { initProgressiveLoad(config); } }
document.addEventListener("DOMContentLoaded", function() { initProgressiveLoad(config); }); document.addEventListener("pjax:complete", function() { onPJAXComplete(config); });
|
- 新建文件
source/css/imgloaded.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 48 49 50
| .pl-container { width: 100%; height: 100%; position: relative; overflow: hidden; will-change: transform; animation: blur-to-clear 2s cubic-bezier(.62,.21,.25,1) 0s 1 normal backwards running, scale 1.5s cubic-bezier(.62,.21,.25,1) 0s 1 both; } .pl-img { width: 100%; height: 100%; position: absolute; background-position: center; background-size: cover; background-repeat: no-repeat; opacity: 0; transition: opacity 1s; }
@keyframes blur-to-clear { 0% { filter: blur(50px); opacity: 1; } 100% { filter: blur(0); opacity: 1; } }
@keyframes scale { 0% { transform: scale(1.5) translateZ(0); opacity: 0; } to { transform: scale(1) translateZ(0); opacity: 1; } }
.pl-visible { opacity: 1; }
.pl-blur { filter: blur(50px); }
|
2、引入文件
- 在
_config.anzhiyu.yml
主题配置文件下inject
配置项中head
和bottom
处 - 分别引入
imgloaded.css
和imgloaded.js
文件
1 2 3 4 5 6 7 8
| inject: head: - <link rel="stylesheet" href="/css/imgloaded.css?1">
bottom: - <script async data-pjax src="/js/imgloaded.js?1"></script> # 首页图片渐进式加载
|
3、配置图片
务必记得在主题配置文件中开启顶部图的功能,也可以像我这样配置空链接。因为js文件已经接替了图片加载功能,此处不需要配置图片(当然你也可以配置上)
1 2
| # The banner image of home page index_img: "background: url() top / cover no-repeat"
|
- 在
imgloaded.js
中第70行至73行
处,也就是以下示例的部分 - 配置自己的图片,可以是图片直链也可以是本地路径
1 2 3 4 5 6 7
| const config = { smallSrc: '/img/xiaotu.jpg', largeSrc: '/img/tu.jpg', mobileSmallSrc: '/img/sjxt.jpg', mobileLargeSrc: '/img/sjdt.jpg', enableRoutes: ['/'], };
|
4、大功告成
到这一步若你配置的图片文件没有问题,可以执行hexo三连查看效果啦!
5、思考
该方案是否还有可优化的点,或者是否有其他用途呢🤔