refactor: (性能优化)使友链页面在桌面端Chromium系浏览器不再卡成史

移除所有图片加载时的进度条动画效果,简化DOM结构和CSS样式
默认使用深色主题,优化主题加载逻辑
清理未使用的代码和注释
This commit is contained in:
二叉树树
2026-01-19 16:23:58 +08:00
parent 4524670b46
commit 27206a7a9b
6 changed files with 33 additions and 235 deletions

View File

@@ -47,40 +47,17 @@ const imageClass = "w-full h-full object-cover";
const imageStyle = `object-position: ${position}`;
---
<div id={id} class:list={[className, 'overflow-hidden relative image-wrapper']} style={`--theme-hue: ${siteConfig.themeColor.hue}`}>
<!-- 加载条 -->
<div class="loading-bar absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-32 h-1 bg-gray-200 dark:bg-gray-700 z-10 rounded-full overflow-hidden">
<div class="loading-progress h-full w-8 bg-[oklch(0.70_0.14_var(--theme-hue))] animate-loading-progress rounded-full"></div>
</div>
<!-- 图片内容 -->
{isLocal && img && <Image src={img} alt={alt || ""} class={`${imageClass} image-content opacity-0 transition-opacity duration-500`} style={imageStyle} onload="this.style.opacity='1'; this.parentElement.querySelector('.loading-bar').style.opacity='0';"/>}
{isLocal && img && <Image src={img} alt={alt || ""} class={`${imageClass} image-content`} style={imageStyle}/>}
{!isLocal && (
imageFallbackConfig.enable && src.includes(imageFallbackConfig.originalDomain) ?
<img src={isPublic ? url(src) : src} alt={alt || ""} class={`${imageClass} image-content opacity-0 transition-opacity duration-500`} style={imageStyle} onload="this.style.opacity='1'; this.parentElement.querySelector('.loading-bar').style.opacity='0';" onerror={`this.onerror=null; this.src='${(isPublic ? url(src) : src).replace(imageFallbackConfig.originalDomain, imageFallbackConfig.fallbackDomain)}';`}/> :
<img src={isPublic ? url(src) : src} alt={alt || ""} class={`${imageClass} image-content opacity-0 transition-opacity duration-500`} style={imageStyle} onload="this.style.opacity='1'; this.parentElement.querySelector('.loading-bar').style.opacity='0';"/>
<img src={isPublic ? url(src) : src} alt={alt || ""} class={`${imageClass} image-content`} style={imageStyle} onerror={`this.onerror=null; this.src='${(isPublic ? url(src) : src).replace(imageFallbackConfig.originalDomain, imageFallbackConfig.fallbackDomain)}';`}/> :
<img src={isPublic ? url(src) : src} alt={alt || ""} class={`${imageClass} image-content`} style={imageStyle}/>
)}
</div>
<style>
.loading-bar {
transition: opacity 0.5s ease-out;
}
@keyframes loading-progress {
0% {
transform: translateX(-100%);
}
100% {
transform: translateX(400%);
}
}
.animate-loading-progress {
animation: loading-progress 1.5s ease-in-out infinite;
}
.image-content {
transition: transform 0.3s ease-out, opacity 0.5s ease-out;
transition: transform 0.3s ease-out;
}
.image-wrapper:hover .image-content {

View File

@@ -6,10 +6,7 @@ const config = profileConfig;
---
<div class="card-base p-3 border border-black/10 dark:border-white/10">
<div class="relative mx-auto mt-1 lg:mx-0 lg:mt-0 mb-3 max-w-[12rem] lg:max-w-none rounded-xl overflow-hidden" style={`--theme-hue: ${siteConfig.themeColor.hue}`}>
<div class="loading-bar absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-32 h-1 bg-gray-200 dark:bg-gray-700 z-10 rounded-full overflow-hidden">
<div class="loading-progress h-full w-8 bg-[oklch(0.70_0.14_var(--theme-hue))] animate-loading-progress rounded-full"></div>
</div>
<img src={config.avatar} alt="Profile Image of the Author" class="w-full h-full object-cover opacity-0 transition-opacity duration-500" onload="this.style.opacity='1'; this.parentElement.querySelector('.loading-bar').style.opacity='0';"/>
<img src={config.avatar} alt="Profile Image of the Author" class="w-full h-full object-cover transition duration-500" />
</div>
<div class="px-2">
<div class="font-bold text-xl text-center mb-1 dark:text-neutral-50 transition">{config.name}</div>
@@ -52,19 +49,6 @@ const config = profileConfig;
.loading-bar {
transition: opacity 0.5s ease-out;
}
@keyframes loading-progress {
0% {
transform: translateX(-100%);
}
100% {
transform: translateX(400%);
}
}
.animate-loading-progress {
animation: loading-progress 1.5s ease-in-out infinite;
}
</style>
<script define:vars={{ umamiConfig}}>

View File

@@ -82,7 +82,7 @@ const bannerOffset =
---
<!DOCTYPE html>
<html lang={siteLang} class="bg-[var(--page-bg)] transition text-[12px] md:text-[16px]"
<html lang={siteLang} class="bg-[var(--page-bg)] transition text-[12px] md:text-[16px] dark"
data-overlayscrollbars-initialize> <!-- 手机端适配 -->
<head>
@@ -136,21 +136,21 @@ const bannerOffset =
localStorage.setItem('theme', DARK_MODE);
} else {
// Load the theme from local storage
const theme = localStorage.getItem('theme') || AUTO_MODE;
switch (theme) {
case LIGHT_MODE:
document.documentElement.classList.remove('dark');
break
case DARK_MODE:
const theme = localStorage.getItem('theme') || DARK_MODE;
switch (theme) {
case LIGHT_MODE:
document.documentElement.classList.remove('dark');
break
case DARK_MODE:
document.documentElement.classList.add('dark');
break
case AUTO_MODE:
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.documentElement.classList.add('dark');
break
case AUTO_MODE:
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');
}
}
} else {
document.documentElement.classList.remove('dark');
}
}
}
// Load the hue from local storage
@@ -161,71 +161,14 @@ const bannerOffset =
let offset = Math.floor(window.innerHeight * (BANNER_HEIGHT_EXTEND / 100));
offset = offset - offset % 4;
document.documentElement.style.setProperty('--banner-height-extend', `${offset}px`);
// // Background image loading detection
// const bgUrl = getComputedStyle(document.documentElement).getPropertyValue('--bg-url').trim();
// const bgEnable = getComputedStyle(document.documentElement).getPropertyValue('--bg-enable').trim();
// if (bgUrl && bgUrl !== 'none' && bgEnable === '1') {
// const img = new Image();
// const urlMatch = bgUrl.match(/url\(["']?([^"')]+)["']?\)/);
// if (urlMatch) {
// img.onload = function() {
// // 背景图片完全加载后,显示背景并启用卡片透明效果
// document.body.classList.add('bg-loaded');
// document.documentElement.style.setProperty('--card-bg', 'var(--card-bg-transparent)');
// document.documentElement.style.setProperty('--float-panel-bg', 'var(--float-panel-bg-transparent)');
// };
// img.onerror = function() {
// // Keep cards opaque if background image fails to load
// console.warn('Background image failed to load, keeping cards opaque');
// };
// img.src = urlMatch[1];
// }
// }
// Random Background Image Integration
// This waits for the external script to define window.getRandomPicH
/*
function setRandomBackground() {
// Check if the external random pic function is available
if (typeof window.getRandomPicH === 'function') {
const bgUrl = window.getRandomPicH();
const bgBox = document.getElementById('bg-box');
if (bgBox && bgUrl) {
console.log('Setting random background:', bgUrl);
const img = new Image();
img.onload = function() {
bgBox.style.backgroundImage = `url('${bgUrl}')`;
bgBox.classList.add('loaded');
bgBox.classList.add('random-loaded'); // Add specific class
console.log('Random background loaded successfully');
// Set CSS variables for transparency effects
document.documentElement.style.setProperty('--card-bg', 'var(--card-bg-transparent)');
document.documentElement.style.setProperty('--float-panel-bg', 'var(--float-panel-bg-transparent)');
};
img.onerror = function() {
console.error('Failed to load random background image:', bgUrl);
};
img.src = bgUrl;
} else {
console.warn('bgBox not found or bgUrl is empty', { bgBox, bgUrl });
}
} else {
// Retry after a short delay if script is not yet loaded
console.log('Waiting for getRandomPicH...');
setTimeout(setRandomBackground, 500);
}
}
// Start attempting to set background
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', setRandomBackground);
} else {
setRandomBackground();
}
*/
</script>
<style define:vars={{ configHue }}>
/* Fallback for no-js: Apply default theme hue */
:root {
--hue: var(--configHue);
}
</style>
<style define:vars={{
configHue,
'page-width': `${PAGE_WIDTH}rem`,

View File

@@ -30,10 +30,7 @@ const friends = Object.values(
<a href={friend.url} target="_blank" class="friend-card">
<div class="flex items-center gap-2">
<div class="relative w-5 h-5 rounded overflow-hidden" style={`--theme-hue: ${siteConfig.themeColor.hue}`}>
<div class="loading-bar absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-32 h-1 bg-gray-200 dark:bg-gray-700 z-10 rounded-full overflow-hidden">
<div class="loading-progress h-full w-8 bg-[oklch(0.70_0.14_var(--theme-hue))] animate-loading-progress rounded-full"></div>
</div>
<img src={friend.avatar} loading="lazy" class="w-full h-full object-cover opacity-0 transition-opacity duration-500" alt={`${friend.name}的头像`} onload="this.style.opacity='1'; this.parentElement.querySelector('.loading-bar').style.opacity='0';"/>
<img src={friend.avatar} loading="lazy" class="w-full h-full object-cover transition-opacity duration-500" alt={`${friend.name}的头像`} />
</div>
<div class="font-bold text-black dark:text-white">{friend.name}</div>
</div>
@@ -79,21 +76,4 @@ const friends = Object.values(
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 0.15s;
}
.loading-bar {
transition: opacity 0.5s ease-out;
}
@keyframes loading-progress {
0% {
transform: translateX(-100%);
}
100% {
transform: translateX(400%);
}
}
.animate-loading-progress {
animation: loading-progress 1.5s ease-in-out infinite;
}
</style>

View File

@@ -262,56 +262,9 @@ const jsonLd = {
</style>
<script define:vars={{ siteConfig }}>
// 图片加载动画处理
// 图片加载处理 (仅用于图片回退逻辑)
function setupImageLoading() {
const markdownContent = document.querySelector('.markdown-content');
if (!markdownContent) return;
const images = markdownContent.querySelectorAll('img');
images.forEach(img => {
// 跳过已经处理过的图片
if (img.parentElement.classList.contains('image-loading-wrapper')) return;
// 创建包裹容器
const wrapper = document.createElement('div');
wrapper.className = 'relative image-loading-wrapper rounded-xl overflow-hidden my-4';
wrapper.style.setProperty('--theme-hue', siteConfig.themeColor.hue);
// 创建加载条
const loadingBar = document.createElement('div');
loadingBar.className = 'loading-bar absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-32 h-1 bg-gray-200 dark:bg-gray-700 z-10 rounded-full overflow-hidden';
loadingBar.innerHTML = `<div class="loading-progress h-full w-8 bg-[oklch(0.70_0.14_var(--theme-hue))] animate-loading-progress rounded-full"></div>`;
// 插入DOM
img.parentNode.insertBefore(wrapper, img);
wrapper.appendChild(loadingBar);
wrapper.appendChild(img);
// 设置图片初始状态
img.style.opacity = '0';
img.style.transition = 'opacity 0.5s ease-out';
loadingBar.style.transition = 'opacity 0.5s ease-out';
// 处理加载完成
const handleLoad = () => {
img.style.opacity = '1';
loadingBar.style.opacity = '0';
setTimeout(() => {
loadingBar.remove();
}, 500);
};
if (img.complete) {
handleLoad();
} else {
img.onload = handleLoad;
img.onerror = () => {
loadingBar.remove();
img.style.opacity = '1';
};
}
});
// 保留此函数用于将来的其他处理,或者彻底删除
}
// 初始化
@@ -376,19 +329,6 @@ const jsonLd = {
</script>
<style is:global>
@keyframes loading-progress {
0% {
transform: translateX(-100%);
}
100% {
transform: translateX(400%);
}
}
.animate-loading-progress {
animation: loading-progress 1.5s ease-in-out infinite;
}
/* 确保包裹容器继承原图的圆角等样式 */
.markdown-content img {
margin: 0 !important; /* 让wrapper来控制margin */

View File

@@ -44,10 +44,7 @@ const sponsors = Object.values(
</div>
<div class="qr-code-placeholder">
<div class="relative w-48 h-48 mx-auto rounded-lg overflow-hidden" style={`--theme-hue: ${siteConfig.themeColor.hue}`}>
<div class="loading-bar absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-32 h-1 bg-gray-200 dark:bg-gray-700 z-10 rounded-full overflow-hidden">
<div class="loading-progress h-full w-8 bg-[oklch(0.70_0.14_var(--theme-hue))] animate-loading-progress rounded-full"></div>
</div>
<img src="/sponsors/alipay.svg" alt="支付宝二维码" class="w-full h-full object-cover opacity-0 transition-opacity duration-500" onload="this.style.opacity='1'; this.parentElement.querySelector('.loading-bar').style.opacity='0';"/>
<img src="/sponsors/alipay.svg" alt="支付宝二维码" class="w-full h-full object-cover transition duration-500" />
</div>
</div>
</div>
@@ -65,10 +62,7 @@ const sponsors = Object.values(
</div>
<div class="qr-code-placeholder">
<div class="relative w-48 h-48 mx-auto rounded-lg overflow-hidden" style={`--theme-hue: ${siteConfig.themeColor.hue}`}>
<div class="loading-bar absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-32 h-1 bg-gray-200 dark:bg-gray-700 z-10 rounded-full overflow-hidden">
<div class="loading-progress h-full w-8 bg-[oklch(0.70_0.14_var(--theme-hue))] animate-loading-progress rounded-full"></div>
</div>
<img src="/sponsors/wechat.svg" alt="微信支付二维码" class="w-full h-full object-cover opacity-0 transition-opacity duration-500" onload="this.style.opacity='1'; this.parentElement.querySelector('.loading-bar').style.opacity='0';"/>
<img src="/sponsors/wechat.svg" alt="微信支付二维码" class="w-full h-full object-cover transition duration-500" />
</div>
</div>
</div>
@@ -129,10 +123,7 @@ const sponsors = Object.values(
<div class="w-10 h-10 rounded-lg flex items-center justify-center overflow-hidden">
{sponsor.avatar ? (
<div class="relative w-full h-full rounded-lg overflow-hidden" style={`--theme-hue: ${siteConfig.themeColor.hue}`}>
<div class="loading-bar absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-32 h-1 bg-gray-200 dark:bg-gray-700 z-10 rounded-full overflow-hidden">
<div class="loading-progress h-full w-8 bg-[oklch(0.70_0.14_var(--theme-hue))] animate-loading-progress rounded-full"></div>
</div>
<img src={sponsor.avatar} alt={`${sponsor.name}的头像`} loading="lazy" class="w-full h-full object-cover opacity-0 transition-opacity duration-500" onload="this.style.opacity='1'; this.parentElement.querySelector('.loading-bar').style.opacity='0';"/>
<img src={sponsor.avatar} alt={`${sponsor.name}的头像`} loading="lazy" class="w-full h-full object-cover transition duration-500" />
</div>
) : (
<Icon name="material-symbols:person" class="text-gray-500 dark:text-gray-400 text-[1.2rem]" />
@@ -199,23 +190,6 @@ const sponsors = Object.values(
color: var(--primary);
opacity: 0.8;
}
.loading-bar {
transition: opacity 0.5s ease-out;
}
@keyframes loading-progress {
0% {
transform: translateX(-100%);
}
100% {
transform: translateX(400%);
}
}
.animate-loading-progress {
animation: loading-progress 1.5s ease-in-out infinite;
}
</style>
<script>