网站主题与图片加载逻辑的优化实现

Jun 2025
Updated Jun 2025

需求背景

在开发基于Hexo的博客网站时,我发现了一个用户体验问题:无论访问网站的时间是白天还是夜间,系统总是默认显示日间模式的图片,即使系统设置为深色模式或当前时间是夜间。这导致必须手动切换主题才能看到与当前主题匹配的图片。

方案设计

  1. 配置文件增强
  2. 主题初始化逻辑优化
  3. 图片加载逻辑改进
  4. 主题变化事件监听机制

1. 配置文件增强

在主题配置文件(_config.yml)中,添加了两个关键设置选项:

theme_settings:
is_dark: false # 是否默认使用深色模式
auto_dark: true # 是否跟随系统主题设置

这些设置允许:

  • 网站可以默认以深色模式加载(通过设置is_dark: true
  • 网站可以自动跟随系统主题设置(通过设置auto_dark: true

2. 主题初始化逻辑优化

优化了layout.ejs中的主题初始化脚本,使其根据以下优先级确定要使用的主题:

  1. 之前手动设置的主题(存储在localStorage中)
  2. 如果启用了自动主题功能且没有设置,则根据系统主题偏好
  3. 如果上述条件都不满足,则使用配置文件中指定的默认主题
// 初始化主题
function initTheme() {
// 检查配置文件中的主题设置
const configIsDark = theme.theme_settings && theme.theme_settings.is_dark;
const configAutoDark = theme.theme_settings && theme.theme_settings.auto_dark;

// 从localStorage获取用户设置
const savedThemePreference = localStorage.getItem('themePreference') || 'auto';
let theme = localStorage.getItem('theme');

if (!theme) {
// 如果配置启用了自动主题
if (configAutoDark) {
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
theme = prefersDark ? 'dark' : 'light';
} else {
// 使用配置文件中的默认设置
theme = configIsDark ? 'dark' : 'light';
}
localStorage.setItem('theme', theme);
}

document.documentElement.setAttribute('data-theme', theme);

// 更新主题图标...
}

3. 图片加载逻辑改进

我修改了index.ejs文件中图片的初始加载逻辑,确保根据当前主题设置显示正确的图片:

<img src="<% if(theme.theme_settings && (theme.theme_settings.is_dark || (theme.theme_settings.auto_dark && window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches))) { %><%= theme.banner_images.top_banner.dark %><% } else { %><%= theme.banner_images.top_banner.light %><% } %>" alt="Banner Background" class="top-banner-image">

这段代码会根据当前的主题设置(is_dark)或系统设置(如果启用了auto_dark)选择显示深色或浅色图片。

4. 动态图片更新函数

实现了一个updateImagesBasedOnTheme()函数,负责在主题变化时更新图片:

function updateImagesBasedOnTheme() {
// 获取当前主题
const currentTheme = document.documentElement.getAttribute('data-theme');
const isDarkMode = currentTheme === 'dark';

// 获取图片元素
const topBannerImage = document.querySelector('.top-banner-image');
const contentBannerImage = document.getElementById('banner-random-image');

// 更新图片源
if (topBannerImage) {
topBannerImage.src = isDarkMode ?
theme.banner_images.top_banner.dark :
theme.banner_images.top_banner.light;
}

if (contentBannerImage) {
contentBannerImage.src = isDarkMode ?
theme.banner_images.content_banner.dark :
theme.banner_images.content_banner.light;
}
}

5. 事件监听机制

添加了事件监听器,以响应主题变化和系统主题变化:

// 初始调用一次确保图片与当前主题匹配
updateImagesBasedOnTheme();

// 监听主题变化事件
document.addEventListener('themeChanged', function(event) {
updateImagesBasedOnTheme();
});

// 监听系统主题变化(如果启用了自动主题)
if (theme.theme_settings && theme.theme_settings.auto_dark) {
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function(e) {
// 只有在自动主题模式下才响应系统主题变化
if (localStorage.getItem('themePreference') === 'auto') {
updateImagesBasedOnTheme();
}
});
}

实施效果

通过这些优化,成功实现了以下效果:

  1. 智能初始加载 - 网站会根据用户的系统设置或偏好自动选择合适的主题和图片
  2. 实时响应 - 当手动切换主题或系统主题发生变化时,图片会立即更新

总结

通过将图片URL集中管理在配置文件中,我也简化了未来的维护工作。当需要更新网站图片时,只需修改配置文件中的URL,而无需修改代码。

New