2025 Murasame
546 字
3 分钟
为 Fuwari 添加开屏动画
WARNING基于 AI 的产物,介意请慎用
一.创建开屏动画组件
在 src/layouts/ 目录下创建 LoadingOverlay.astro 文件:
---import { siteConfig } from "@/config";
interface Props { enable?: boolean; text?: string; duration?: number;}
const { enable = siteConfig.preloader.enable, text = siteConfig.preloader.text || siteConfig.title, duration = siteConfig.preloader.duration} = Astro.props;---
{enable && ( <div class="preloader"> <h2 class="ml13">{text}</h2> </div>)}
<style is:global> .preloader { position: fixed; display: flex; justify-content: center; align-items: center; width: 100vw; height: 100vh; background-color: var(--page-bg); z-index: 1100; transition: opacity 0.3s ease-in-out; }
.ml13 { font-size: 3.2rem; color: var(--primary); letter-spacing: -1px; font-weight: 500; text-align: center; opacity: 0; }
.ml13.ready { opacity: 1; }
.ml13 .word { display: inline-flex; flex-wrap: wrap; white-space: nowrap; }
.ml13 .letter { display: inline-block; line-height: 1em; opacity: 0; transform: translateY(25px); filter: blur(5px); transition: opacity 0.6s ease-out, transform 0.6s ease-out, filter 0.6s ease-out; }</style>
<script define:vars={{ preloaderDuration: duration }}> function initPreloader() { const textWrapper = document.querySelector('.ml13'); if (!textWrapper) return;
const words = textWrapper.textContent?.trim().split(' ') || []; textWrapper.innerHTML = '';
words.forEach((word) => { const wordSpan = document.createElement('span'); wordSpan.classList.add('word'); wordSpan.innerHTML = word.replace(/\S/g, "<span class='letter'>$&</span>"); textWrapper.appendChild(wordSpan); textWrapper.appendChild(document.createTextNode(' ')); });
// 文字分割完成,显示容器 textWrapper.classList.add('ready');
function hidePreloader() { const preloader = document.querySelector('.preloader'); if (preloader) { preloader.style.opacity = '0'; setTimeout(() => { preloader.style.display = 'none'; }, 300); } }
// 使用 requestAnimationFrame 确保动画流畅 const letters = document.querySelectorAll('.ml13 .letter');
// 等待浏览器渲染完成后再开始动画 requestAnimationFrame(() => { requestAnimationFrame(() => { // 淡入动画 - 增加初始延迟确保稳定性 letters.forEach((letter, i) => { setTimeout(() => { letter.style.opacity = '1'; letter.style.transform = 'translateY(0)'; letter.style.filter = 'blur(0px)'; }, 500 + i * 30); });
// 使用配置的时长控制淡出时机 const fadeOutDelay = preloaderDuration * 0.6; // 60% 时开始淡出 setTimeout(() => { letters.forEach((letter, i) => { setTimeout(() => { letter.style.opacity = '0'; letter.style.transform = 'translateY(-50px)'; letter.style.filter = 'blur(5px)'; }, i * 15); });
// 计算最后一个字母完全淡出的时间 const lastLetterDelay = (letters.length - 1) * 15; // 最后一个字母开始淡出的延迟 const transitionDuration = 250; // CSS transition 时长 0.6s const totalFadeOutTime = lastLetterDelay + transitionDuration;
// 等待所有文字完全淡出后再隐藏遮罩 setTimeout(hidePreloader, totalFadeOutTime); }, fadeOutDelay); }); });
// 页面加载完成后也隐藏(备用方案) window.addEventListener('load', () => { setTimeout(hidePreloader, preloaderDuration); }); }
// 确保 DOM 完全准备好 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initPreloader); } else { initPreloader(); }</script>二.添加配置文件
在 src 目录下编辑 config.ts 文件添加以下内容:
preloader: { enable: true, // 启用页面加载遮罩 text: "(∠・ω< )⌒★", // 自定义显示文字,留空则使用网站标题 duration: 2000, // 遮罩显示时长(毫秒)} 为 Fuwari 添加开屏动画
https://fuwari.vercel.app/posts/blog/add-welcome-overlay/