Files
frontend_v2/src/components/LoadingScreen.astro
toom1996 36f3ad039f
Some checks failed
deploy / deploy (push) Has been cancelled
update
2026-09-03 19:45:36 +08:00

159 lines
4.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。
// - 样式作用域隔离在 #loading-screen 内(is:global,因选择器基于唯一 id,不影响整站黑白调性)。
// - 隐藏逻辑用 Astro 默认打包的 <script>(module / defer),无需 is:inline;
// 模块脚本在 window.load 之前执行,故 addEventListener('load') 必然先挂上,无竞态。
// - Raleway 字体仅加载屏使用,随组件引入(Astro 自动 hoist 到 head)。
---
<div id="loading-screen" aria-hidden="true">
<div id="wrapper">
<div id="container">
<h1>Portfolio Studio</h1>
<p class="ls-sub">Loading</p>
</div>
</div>
</div>
<style>
#loading-screen {
position: fixed;
inset: 0;
z-index: 9999;
display: flex;
flex-direction: column;
justify-content: center;
background-color: #ffffff;
color: #0a0a0a;
font: 16px/1.25 'Raleway', sans-serif;
text-align: center;
transition: opacity 0.5s ease;
}
#loading-screen.is-hidden {
opacity: 0;
pointer-events: none;
}
#loading-screen *,
#loading-screen *:before,
#loading-screen *:after {
box-sizing: border-box;
}
#loading-screen #wrapper {
margin-left: auto;
margin-right: auto;
max-width: 80em;
}
#loading-screen #container {
display: flex;
flex-direction: column;
justify-content: center;
min-height: 100vh;
padding: 1em;
width: 100%;
}
#loading-screen h1 {
animation: ls-text-shadow 1.5s ease-in-out infinite;
font-size: clamp(2.5rem, 8vw, 5rem);
font-weight: 900;
line-height: 1;
}
#loading-screen h1:hover {
animation-play-state: paused;
}
#loading-screen a {
color: #0a0a0a;
}
#loading-screen a:hover {
text-decoration: none;
}
#loading-screen .ls-sub {
margin-top: 1.5em;
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
font-size: 0.75rem;
letter-spacing: 0.3em;
text-transform: uppercase;
color: #888;
}
/* 关键帧独立命名(ls- 前缀),避免与站点其它 keyframes 冲突 */
@keyframes ls-text-shadow {
0% {
transform: translateY(0);
text-shadow:
0 0 0 #000,
0 0 0 #3a3a3a,
0 0 0 #777,
0 0 0 #bbb;
}
20% {
transform: translateY(-1em);
text-shadow:
0 0.125em 0 #000,
0 0.25em 0 #3a3a3a,
0 -0.125em 0 #777,
0 -0.25em 0 #bbb;
}
40% {
transform: translateY(0.5em);
text-shadow:
0 -0.0625em 0 #000,
0 -0.125em 0 #3a3a3a,
0 0.0625em 0 #777,
0 0.125em 0 #bbb;
}
60% {
transform: translateY(-0.25em);
text-shadow:
0 0.03125em 0 #000,
0 0.0625em 0 #3a3a3a,
0 -0.03125em 0 #777,
0 -0.0625em 0 #bbb;
}
80% {
transform: translateY(0);
text-shadow:
0 0 0 #000,
0 0 0 #3a3a3a,
0 0 0 #777,
0 0 0 #bbb;
}
}
/* 尊重系统“减少动画”偏好:仅作用于加载屏,不波及整站 */
@media (prefers-reduced-motion: reduce) {
#loading-screen *,
#loading-screen *:before,
#loading-screen *:after {
animation: none !important;
transition: none !important;
}
}
</style>
<script>
// 页面 load 后淡出加载屏;最少展示 500ms 防闪烁,最多 3s 兜底。
// 作为 Astro 默认打包的 module 脚本(defer),在 window.load 前执行,监听必然先挂上。
(function () {
var el = document.getElementById('loading-screen');
if (!el) return;
var hidden = false;
function hide() {
if (hidden) return;
hidden = true;
el.classList.add('is-hidden');
setTimeout(function () {
el.style.display = 'none';
}, 600);
}
var start = Date.now();
function tryHide() {
var waited = Date.now() - start;
if (waited >= 500) hide();
else setTimeout(hide, 500 - waited);
}
if (document.readyState === 'complete') tryHide();
else window.addEventListener('load', tryHide);
setTimeout(hide, 3000);
})();
</script>