本文修改主题为AnZhiYu
主题,若使用其他主题,请自行确认修改位置。
原文出处
https://blog.kouseki.cn/posts/4f72.html
https://satera.cn/posts/6a8fb549/
https://blhorizon.github.io/posts/29ff7730.html
效果预览
查看图片
修改步骤
以本站使用的主题anzhiyu
为例(butterfly通用),为首页顶部图配置渐进式加载。这个方法应该也同样适用于一图流的博客背景,有需要的朋友可以自己研究一下~
1. 图片加载JS
新建文件[Blogroot]\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
|
if (!window.ProgressiveLoad) {
class ProgressiveLoad { constructor(smallSrc, largeSrc) { this.smallSrc = smallSrc; this.largeSrc = largeSrc; this.initScrollListener(), this.initTpl(); } initScrollListener() { window.addEventListener("scroll", (()=>{ var e = Math.min(window.scrollY / window.innerHeight, 0.7); this.container.style.setProperty("--process", e) } )) }
initTpl() { this.container = document.createElement('div'); this.smallStage = document.createElement('div'); this.largeStage = document.createElement('div'); this.video = document.createElement('div'); this.smallImg = new Image(); this.largeImg = new Image(); this.container.className = 'pl-container'; this.container.style.setProperty("--process", 0), this.smallStage.className = 'pl-img pl-blur'; this.largeStage.className = 'pl-img'; this.video.className = 'pl-video'; this.container.appendChild(this.smallStage); this.container.appendChild(this.largeStage); this.container.appendChild(this.video); 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) => { 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: 'https://www.loliapi.com/acg/', largeSrc: 'https://www.loliapi.com/acg/', mobileSmallSrc: 'https://www.loliapi.com/acg/', mobileLargeSrc: 'https://www.loliapi.com/acg/', enableRoutes: ['/'], };
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); } }
document.addEventListener("DOMContentLoaded", function() { initProgressiveLoad(config); });
document.addEventListener("pjax:complete", function() { onPJAXComplete(config); });
}
|
2. 新建样式文件
新建文件[Blogroot]\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 53 54
| .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); }
|
3. 引入JS和CSS
在_config.anzhiyu.yml
主题配置文件下inject
配置项中head
和bottom
处引入两个文件
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> # 首页图片渐进式加载
|
4. 配置顶图
配置顶图,务必记得在主题配置文件中开启顶部图的功能,也可以像我这样配置空链接。因为js文件已经接替了图片加载功能,此处不需要配置图片(当然你也可以配置上)
1
| index_img: "background: url() top / cover no-repeat"
|
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: ['/'], };
|
图片懒加载配置修改
为了使图片模糊效果更加平滑,可以尝试修改lazyload
配置项。
在主题配置文件中找到lazyload
,将field
项改为post
,blur
维持true
1 2 3 4 5 6
| lazyload: enable: true field: post placeholder: blur: true progressive: true
|
常见问题
- 首页图下方的有个奇怪的边界的情况(还有一图流的时候,自行设计渐变)
- 如果大图的下边界有不透明度变化,模糊小图,小图会超出不透明度范围,露出小图
- 如果开了夜间模式,是因为由夜间模式的阅读模式叠加一层0.3的alpha,具体是
[Blogroot]\themes\anzhiyu\source\css\_mode\darkmode.styl
文件里的background-color: alpha($dark-black, 0.3)
,改为1 2 3 4 5 6
| background-image: linear-gradient( to bottom, rgba($dark-black, 0.1) 0%, rgba($dark-black, 0) 75%, rgba($dark-black, 0) 100% );
|
拓展修改
此方法修改后,首页背景图的加载效果可以达到较好的效果,但其他页面并不会加载首页的背景图,如果需要所有页面都加载,则需要进一步修改。
这里我选择直接将背景图挂载到 #web_bg 元素下,直接当做背景,这样可以实现所有页面都加载首页背景图。
修改步骤
修改[Blogroot]\themes\anzhiyu\layout\includes\layout.pug
文件
此步骤是因为JS文件中挂载元素会先检查有无full_page属性,所以需要先将header元素加上full_page属性。你也可以选择去除属性检查,直接挂载到 #web_bg 元素下,忽略此步骤。
1 2 3
| #web_bg + header#web-header(class="full_page") #an_music_bg
|
修改[Blogroot]\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 53
| body[style*="--animate: true"] #nav, body[style*="--animate: true"] #scroll-down, body[style*="--animate: true"] #site-info { -webkit-animation: scale 2.2s cubic-bezier(.6, .1, .25, 1) .5s 1 backwards; animation: scale 2.2s cubic-bezier(.6, .1, .25, 1) .5s 1 backwards }
@media screen and (max-width: 768px) { .pl-container { top: 0; } }
@media screen and (min-width: 768px) {
#page-header.full_page, #web-header.full_page, .pl-container { height: 100vh }
#page-header.full_page.expand-to-full, #web-header.full_page.expand-to-full, .pl-container.expand-to-full { height: 50vh !important }
.pl-container { will-change: opacity, transform, filter; opacity: calc(1 - var(--process) * 1) !important; transform: scale(calc(1 + var(--process) * .1)); filter: blur(calc(var(--process) * 10px)); } }
.pl-container { width: 100%; height: 100%; left: 0; position: fixed; z-index: -2; overflow: hidden; }
body[style*="--animate: true"] .pl-container { will-change: transform; animation: blur-to-clear 2.5s cubic-bezier(.6, .25, .25, 1) 0s 1 backwards, scale 2.2s cubic-bezier(.6, .1, .25, 1) .5s 1 backwards; }
[data-theme=dark] .pl-container { filter: brightness(0.6) }
|
修改[Blogroot]\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 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
function getRandomImage(platform) { const num = Math.floor(Math.random() * 300) + 100; if (platform === 'pc') { return `https://img.loliapi.com/i/pc/img${num}.webp`; } else if (platform === 'pe') { return `https://img.loliapi.com/i/pe/img${num}.webp`; } }
if (typeof initLargeSrc === 'undefined') { initLargeSrc = getRandomImage('pc'); } if (typeof initSmallSrc === 'undefined') { initSmallSrc = getRandomImage('pe'); }
if (!window.ProgressiveLoad) { class ProgressiveLoad { constructor(smallSrc, largeSrc) { this.smallSrc = smallSrc; this.largeSrc = largeSrc; this.initTpl(); this.initScrollListener(); } initScrollListener() { const header = document.getElementById('page-header'); if (header && header.classList.contains('full_page')) { document.body.style.setProperty('--animate', 'true'); window.addEventListener("scroll", (()=>{ var e = Math.min(window.scrollY / window.innerHeight, 0.7); this.container.style.setProperty("--process", e) } )) } else { this.container.style.setProperty("--process", 0.7) } }
initTpl() { this.container = document.createElement('div'); this.smallStage = document.createElement('div'); this.largeStage = document.createElement('div'); this.video = document.createElement('div'); this.smallImg = new Image(); this.largeImg = new Image(); this.container.className = 'pl-container'; this.container.style.setProperty("--process", 0), this.smallStage.className = 'pl-img pl-blur'; this.largeStage.className = 'pl-img'; this.video.className = 'pl-video'; this.container.appendChild(this.smallStage); this.container.appendChild(this.largeStage); this.container.appendChild(this.video); 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.length > 0) { target.insertBefore(loader.container, target.children[0]); } else { target.appendChild(loader.container); } loader.progressiveLoad(); };
const config = { smallSrc: initLargeSrc, largeSrc: initLargeSrc, mobileSmallSrc: initSmallSrc, mobileLargeSrc: initSmallSrc, enableRoutes: ['/'], };
function initProgressiveLoad(config) { const container = document.querySelector('.pl-container'); if (container) { container.remove(); } const target = document.getElementById('web-header'); if (target && target.classList.contains('full_page')) { executeLoad(config, target); } }
function onPJAXComplete(config) { const target = document.getElementById('web-header'); if (target && target.classList.contains('full_page')) { initProgressiveLoad(config); } }
document.addEventListener("DOMContentLoaded", function() { initProgressiveLoad(config); });
document.addEventListener("pjax:complete", function() { initProgressiveLoad(config); });
}
|
修改#web_bg
的css样式,将其改为背景图样式,可以加在你的自定义样式文件中
1 2 3 4 5 6 7 8 9 10 11 12
| #web_bg { position: fixed; transform: rotate(0deg); top: 0; left: 0; width: 100vw; height: 100vh; display: flex; align-items: center; justify-content: center; z-index: -2; }
|