前情提要
1. 获取当前模式
要解决的第一件事是获取当前页面采用的模式。
按F12打开控制台,很容易发现
1 2 3 4
| <a class="nav-link" target="_self" href="javascript:;" aria-label="Color Toggle"> <i class="iconfont icon-dark" id="color-toggle-icon" data="light"> </i> </a>
|
其中:
class="iconfont icon-dark"
指的是当前显示的按钮图标,当鼠标悬停在上方时就会发生改变,所以我们需要的不是这个
id="color-toggle-icon"
可以通过唯一id获取这个对象
data="light"
记录的是当前所在的模式,正是我们需要的
因此,要获取当前的模式,只需要在自定义js文件backgroundize.js
中写入以下代码
1 2 3 4 5 6
| document.querySelector('#color-toggle-btn').addEventListener( "click", () => { const dataValue = document.getElementById('color-toggle-icon').getAttribute('data'); console.log('data属性值是:', dataValue); } )
|
打开控制台看看效果:

发现获取的data值和当前页面的实际模式刚好相反,这个问题不大,比较烦人的是每一次点击按钮控制台都会打印出两个完全相同的值。通过检查按钮的属性,发现这个click事件被重复绑定两次。
解决方法:定义一个全局变量作为标记,初始值为undefined
,绑定一次之后赋值为true
,因此以后不会重复绑定。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| function getCurrentMode() { return document.getElementById('color-toggle-icon').getAttribute('data'); }
if (!window._colorToggleInitialized) { function handleColorToggle() { console.log(getCurrentMode()); }
document.querySelector('#color-toggle-btn').addEventListener("click", handleColorToggle); window._colorToggleInitialized = true; }
|
修改后的效果:
backgroundize.js只被绑定一次
可以看出非用户自定义的文件也有被重复绑定的情况,原因暂时不太清楚。
2. 替换背景图
文章页的背景图:
1
| <div id="web_bg" style="background-image: url("/img/girl.webp");position: fixed;width: 100%;height: 100%;z-index: -1;background-size: cover;"></div>
|
首页的背景图:
1
| <div id="web_bg" style="background-image: url("/img/miku.webp");position: fixed;width: 100%;height: 100%;z-index: -1;background-size: cover;"></div>
|
注意仅从html上已经无法区分这两张图片,而我的目标是只在文章页的时候启用切换。注意到文章页和首页的<head>
标签
1 2
| <meta property="og:type" content="article"> <meta property="og:type" content="website">
|
所以可以从这里下手进行区分。完整的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
| if (!window._colorToggleInitialized) {
document.querySelector('#color-toggle-btn').addEventListener("click", setBackgroundImage);
window._colorToggleInitialized = true; }
function getCurrentMode() { return document.getElementById('color-toggle-icon').getAttribute('data'); }
function setBackgroundImage() {
const ogTypeMeta = document.querySelector('meta[property="og:type"]'); const isPost = ogTypeMeta && ogTypeMeta.content === 'article';
if (isPost) { const bgDiv = document.getElementById('web_bg');
if (bgDiv) {
if (getCurrentMode() === 'light') bgDiv.style.backgroundImage = 'url("/img/night.webp")';
else bgDiv.style.backgroundImage = 'url("/img/girl.webp")';
} }
}
document.addEventListener('DOMContentLoaded', function () { const ogTypeMeta = document.querySelector('meta[property="og:type"]'); const isPost = ogTypeMeta && ogTypeMeta.content === 'article';
if (isPost) {
const bgDiv = document.getElementById('web_bg');
if (bgDiv) {
if (getCurrentMode() === 'light') bgDiv.style.backgroundImage = 'url("/img/night.webp")';
else bgDiv.style.backgroundImage = 'url("/img/girl.webp")';
} } });
|
然后再加入css代码
1 2 3 4 5 6 7 8 9 10 11
| #web_bg { transition: background-image 0.5s ease-in-out !important; }
@media (prefers-color-scheme: dark) { #web_bg { transition-duration: 0.8s !important; } }
|
因为这里采用的逻辑是只有检测到加载的页面是文章页时才执行北京替换的逻辑,所以使用了两处替换背景的功能:初次加载页面时、按下日夜切换按钮时。
遗留问题
上面的实现方式有一个缺陷:刚进入文章页时有概率先显示出config.fluid.yml
中配置的原背景图,再渐变转换成预期的背景图,看起来比较突兀。因为我之前配置过预加载功能,所以干脆直接把原背景图换成和加载页面相同底色的图了。
另外,在文章页内第一次点击日夜切换按钮时,因为背景图只有在需要它的时候才会开始加载,所以第一次背景会闪烁一下然后突然出现背景图,后续再次切换模式的时候才会正常。要解决这个问题就要使用预加载,提前加载背景图片,不过我目前并不清楚预加载的具体实现方式,所以暂时就先这样了。