1. 效果预览
2. 代码实现
2.1 首页顶部图渐进式加载
- Path: 新建文件
themes/anzhiyu/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
|
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); });
|
- Path: 新建文件
themes/anzhiyu/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 51 52
| .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.2 首页一图流渐进式加载
- Path: 新建文件
themes/anzhiyu/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 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
|
(function() { class ProgressiveLoad { constructor(smallSrc, largeSrc) { this.smallSrc = smallSrc; this.largeSrc = largeSrc; this.initTpl(); this.container.addEventListener('animationend', () => { this.smallStage.style.display = 'none'; }, {once: true}); }
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 ldconfig = { light: { smallSrc: '/img/bg2_80kbver.jpg', largeSrc: '/img/bg2.jpg', mobileSmallSrc: '/img/bg2_80kbver.jpg', mobileLargeSrc: '/img/bg2.jpg', enableRoutes: ['/'], }, dark: { smallSrc: '/img/bg1_80kbver.jpg', largeSrc: '/img/bg1.jpg', mobileSmallSrc: '/img/bg1_80kbver.jpg', mobileLargeSrc: '/img/bg1.jpg', enableRoutes: ['/'], }, };
const getCurrentTheme = () => { return document.documentElement.getAttribute('data-theme'); }
const onThemeChange = () => { const currentTheme = getCurrentTheme(); const config = ldconfig[currentTheme]; initProgressiveLoad(config); document.addEventListener("DOMContentLoaded", function() { initProgressiveLoad(config); }); document.addEventListener("pjax:complete", function() { onPJAXComplete(config); }); }
let initTheme = getCurrentTheme(); let initConfig = ldconfig[initTheme]; initProgressiveLoad(initConfig);
const observer = new MutationObserver(mutations => { mutations.forEach(mutation => { if (mutation.attributeName === "data-theme" && location.pathname === '/') { onThemeChange(); } }); }); observer.observe(document.documentElement, { attributes: true, attributeFilter: ["data-theme"] });
function initProgressiveLoad(config) { const container = document.querySelector('.pl-container'); if (container) { container.remove(); } 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); } }
})();
|
- Path:新建文件
themes/anzhiyu/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 51
| .pl-container { width: 100%; height: 100%; z-index: -2; position: fixed; 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); }
|
3. 引入文件
- 在
_config.anzhiyu.yml
主题配置文件下 inject
配置项中 head
和 bottom
处
- 分别引入
imgloaded.css
和 imgloaded.js
文件
1 2 3 4 5 6
| inject: head: - <link rel="stylesheet" href="/css/imgloaded.css?1"> bottom: - <script async data-pjax src="/js/imgloaded.js?1"></script>
|
- 配置图片
- 为了使用顶部图功能,你必须在主题配置文件中设置
top_image
为 true。然后,你可以在 top_image_url
中留空或者填写任意字符串,因为这个值不会影响图片的显示。图片的加载和渲染是由 js 文件实现的,所以你不需要在配置文件中提供图片的源地址。
1 2
| index_img: "background: url() top / cover no-repeat"
|
- 在
imgloaded.js
中的 73 到 76 行(或是 83 到 86 行)修改以下示例的部分
- 若是首页一图流渐进式加载的
imgloaded.js
则修改 56 到 71 行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| const ldconfig = { light: { smallSrc: 'https://blog.bornforthis.cn/img/bg2_80kbver.jpg', largeSrc: 'https://blog.bornforthis.cn/img/bg2.jpg', mobileSmallSrc: 'https://blog.bornforthis.cn/img/bg2_80kbver.jpg', mobileLargeSrc: 'https://blog.bornforthis.cn/img/bg2.jpg', enableRoutes: ['/'], }, dark: { smallSrc: 'https://blog.bornforthis.cn/img/bg1_80kbver.jpg', largeSrc: 'https://blog.bornforthis.cn/img/bg1.jpg', mobileSmallSrc: 'https://blog.bornforthis.cn/img/bg1_80kbver.jpg', mobileLargeSrc: 'https://blog.bornforthis.cn/img/bg1.jpg', enableRoutes: ['/'], }, };
|
4. 图片懒加载配置修改
1 2 3 4 5 6
| lazyload: enable: true field: post placeholder: blur: true progressive: true
|
5. 大功告成
到这时候,如果你的图片文件配置正确,可以执行 Hexo 的三连命令来查看效果了!
🪧
公众号:AI悦创【二维码】
AI悦创·编程一对一
AI悦创·推出辅导班啦,包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」,全部都是一对一教学:一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然,还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线,随时响应!微信:Jiabcdefh
C++ 信息奥赛题解,长期更新!长期招收一对一中小学信息奥赛集训,莆田、厦门地区有机会线下上门,其他地区线上。微信:Jiabcdefh
方法一:QQ
方法二:微信:Jiabcdefh