update
This commit is contained in:
118
src/components/LoadingOverlay.astro
Normal file
118
src/components/LoadingOverlay.astro
Normal file
@ -0,0 +1,118 @@
|
||||
---
|
||||
// 加载屏:首屏/整页切换时遮盖未渲染内容,避免 FOUC。
|
||||
// 轻量原则(用户要求"朴实流畅"):
|
||||
// - 只用静态大字 + mono 小标 + 一条 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-family: ui-serif, Georgia, Cambria, 'Times New Roman', serif;
|
||||
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-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
||||
font-size: 0.72rem;
|
||||
letter-spacing: 0.34em;
|
||||
text-transform: uppercase;
|
||||
color: #888;
|
||||
animation: ls-pulse 1.4s ease-in-out infinite;
|
||||
}
|
||||
#loading-screen .ls-bar {
|
||||
margin-top: 2em;
|
||||
width: min(180px, 60vw);
|
||||
height: 2px;
|
||||
background: #e6e6e6;
|
||||
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>
|
||||
Reference in New Issue
Block a user