Files
frontend_v2/src/components/LoadingOverlay.astro
toom1996 4b409b5a29 update
2026-09-20 00:44:14 +08:00

117 lines
3.1 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
// 加载屏:首屏/整页切换时遮盖未渲染内容,避免 FOUC。
// 轻量原则(追求朴实流畅):
// - 只用静态大字 + 小标 + 一条 2px 细线进度(transform/opacity 动画,最便宜);
// - 去掉昂贵的多层 text-shadow 位移动画与外部字体;最短展示时间压缩到 ~350ms,跟手不拖沓。
import { config } from '@/lib/config';
import { getI18n } from '@/lib/i18n'
const { t } = getI18n(Astro)
---
<div id="loading-screen" aria-hidden="true">
<div id="ls-box">
<h1>{config.siteName}</h1>
<p class="ls-sub">{t('loading')}</p>
<div class="ls-bar" aria-hidden="true"></div>
</div>
</div>
<style>
#loading-screen {
position: fixed;
inset: 0;
z-index: 9999;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background-color: #ffffff;
color: #0a0a0a;
transition: opacity 0.4s ease;
}
#loading-screen.is-hidden {
opacity: 0;
pointer-events: none;
}
#loading-screen h1 {
margin: 0;
font-size: clamp(2.2rem, 6vw, 4rem);
font-weight: 900;
line-height: 1;
letter-spacing: -0.02em;
text-transform: uppercase;
}
#loading-screen .ls-sub {
margin: 1.1em 0 0;
font-size: 0.72rem;
letter-spacing: 0.34em;
text-transform: uppercase;
color: var(--c-gray-700);
animation: ls-pulse 1.4s ease-in-out infinite;
}
#loading-screen .ls-bar {
margin-top: 2em;
width: min(180px, 60vw);
height: 2px;
background: var(--c-gray-300);
overflow: hidden;
}
#loading-screen .ls-bar::before {
content: "";
display: block;
width: 100%;
height: 100%;
background: #0a0a0a;
transform-origin: left center;
animation: ls-bar 1.1s cubic-bezier(0.4, 0, 0.2, 1) infinite;
}
@keyframes ls-pulse {
0%, 100% { opacity: 0.35; }
50% { opacity: 1; }
}
@keyframes ls-bar {
0% { transform: scaleX(0.08); }
45% { transform: scaleX(0.72); }
100% { transform: scaleX(1); }
}
/* 尊重系统"减少动画"偏好 */
@media (prefers-reduced-motion: reduce) {
#loading-screen .ls-sub,
#loading-screen .ls-bar::before {
animation: none;
}
#loading-screen .ls-bar::before { transform: scaleX(1); }
}
</style>
<script>
// load 后淡出;最少展示 350ms 防闪烁,最多 2s 兜底。
(function () {
const el = document.getElementById('loading-screen');
if (!el) return;
const screen = el; // 已收窄为非空;闭包内 TS 不保留对 el 的收窄,故另存一份
var hidden = false;
function hide() {
if (hidden) return;
hidden = true;
screen.classList.add('is-hidden');
setTimeout(function () {
screen.style.display = 'none';
}, 500);
}
var start = Date.now();
function tryHide() {
var waited = Date.now() - start;
if (waited >= 350) hide();
else setTimeout(hide, 350 - waited);
}
if (document.readyState === 'complete') tryHide();
else window.addEventListener('load', tryHide);
setTimeout(hide, 2000);
})();
</script>