update
Some checks failed
deploy / deploy (push) Has been cancelled

This commit is contained in:
toom1996
2026-09-03 19:45:36 +08:00
parent 6902376bc2
commit 36f3ad039f
14 changed files with 672 additions and 124 deletions

View File

@ -0,0 +1,158 @@
---
// 加载屏组件:首屏/路由切换时遮盖未加载内容,避免 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>