婚禮邀請函
by j91157j91157
HTML
<!-- 在外部 CSS 載入前就蓋住畫面,防止背景閃爍 -->
<link rel="stylesheet" href="style.css" />
<link href="https://unpkg.com/[email protected]/dist/aos.css" rel="stylesheet" />
<!-- 引入 Google Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link
href="https://fonts.googleapis.com/css2?family=Noto+Serif+TC:wght@400;700&family=Noto+Sans+TC:wght@300;400;500;700&display=swap"
rel="stylesheet" />
<link href="https://fonts.googleapis.com/css2?family=Chiron+GoRound+TC:[email protected]&display=swap" rel="stylesheet">
<!-- Vanta Fog 背景容器 -->
<div id="vanta-bg"></div>
<!-- 載入畫面:必須在所有外部資源之前,確保第一幀就蓋住畫面 -->
<div class="loader" id="loader">
<div class="loader-content">
<div class="heart-loader">
<div class="heart-wrapper">
<div class="heart"></div>
</div>
<div class="heart-wrapper">
<div class="heart"></div>
</div>
</div>
<p class="loader-text">Loading...</p>
</div>
</div>
<div class="global-petals-container" id="globalPetalsContainer"></div>
<!-- 漢堡選單按鈕 -->
<button class="menu-toggle" onclick="toggleMenu()" aria-label="開啟選單">
<span></span>
<span></span>
<span></span>
</button>
<!-- 側邊導航列 -->
<nav class="sidebar" id="sidebar">
<div class="sidebar-header">
<h3>💕 選單</h3>
<button class="close-btn" onclick="toggleMenu()">✕</button>
</div>
<div class="nav-links">
<a href="#home" onclick="toggleMenu()">
<span class="icon">🏠</span>
<span>首頁</span>
</a>
<a href="#date" onclick="toggleMenu()">
<span class="icon">📅</span>
<span>婚宴日期</span>
</a>
<a href="#location" onclick="toggleMenu()">
<span class="icon">📍</span>
<span>婚宴地點</span>
</a>
<a href="#schedule" onclick="toggleMenu()">
<span class="icon">⏰</span>
<span>婚禮流程</span>
</a>
<a href="#gallery" onclick="toggleMenu()">
...
CSS
/* ==================== 基礎設定 ==================== */
:root {
--primary: #c5a4f8;
--secondary: #8fa8d8;
--accent: #ede0ff;
--dark: #212529;
--mid: #495057;
--muted: #adb5bd;
--light-purple: #f0e8ff;
--soft: #f8f5ff;
--blue-purple: #a78bfa;
--green-muted: #6c757d;
--gold: #d4af37;
--gradient-main: linear-gradient(135deg, #c5a4f8 0%, #8fa8d8 100%);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
scroll-behavior: smooth;
overflow-x: hidden;
}
/* ==================== Vanta Fog 背景 ==================== */
body {
font-family: 'Noto Sans TC', sans-serif;
line-height: 1.8;
color: var(--dark);
overflow-x: hidden;
background-color: transparent;
}
/* Vanta 固定背景容器 */
#vanta-bg {
position: fixed;
top: 0;
left: 0;
width: 100%;
/* fallback:舊瀏覽器 */
height: 100vh;
/* lvh = Largest Viewport Height,網址列隱藏時的最大高度,避免底部白塊 */
height: 100lvh;
z-index: -1;
}
/* 固定 SVG 背景層(停用) */
#svg-bg {
display: none;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
}
/* ==================== 載入畫面 ==================== */
.loader {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(135deg, #c5d8f5 0%, #d4c5f5 100%);
display: flex;
align-items: center;
justify-content: center;
z-index: 99999;
transition: opacity 0.5s, visibility 0.5s;
}
.loader.hidden {
opacity: 0;
visibility: hidden;
}
.loader-content {
text-align: center;
}
.heart-loader {
position: relative;
width: 100px;
height: 100px;
margin: 0 auto 30px;
display: flex;
align-items: center;
justify-content: center;
}
/* 包裝層 - 負責旋轉 */
.heart-wrapper {
position: absolute;
transform: rotate(-45deg);
/* 固定旋轉角度 */
}
/* 愛心本體 - 只負責縮放動畫...
JavaScript
// ==================== 初始化 ====================
document.addEventListener('DOMContentLoaded', function () {
AOS.init({
duration: 1000,
once: true,
offset: 100,
easing: 'ease-out-cubic',
});
initVantaBg();
initLoader();
initPetals();
initGallery();
initScrollEffects();
initCountdownDisplay();
initScrollAnimations();
console.log('💕 電子喜帖載入完成!');
});
// ==================== Vanta Fog 背景 ====================
function initVantaBg() {
if (typeof VANTA === 'undefined' || typeof VANTA.FOG === 'undefined') return;
const vantaEffect = VANTA.FOG({
el: '#vanta-bg',
mouseControls: true,
touchControls: true,
gyroControls: false,
// 色系:以網頁的紫色、藍紫、玫瑰金為主
highlightColor: 0xf0d6ff, // 淡薰衣草紫(亮部)
midtoneColor: 0xc5a4f8, // 主紫色(中間調)
lowlightColor: 0x8fa8d8, // 藍紫(暗部)
baseColor: 0xf5eeff, // 極淡紫白(底色)
blurFactor: 0.62, // 霧感模糊程度
speed: 1.2, // 流動速度(慢一點更浪漫)
zoom: 0.8, // 縮放(稍微拉遠讓霧更大片)
});
// 保底:舊裝置不支援 lvh 時,監聽 resize 強制更新 canvas 尺寸
// 使用 debounce 避免 resize 觸發過於頻繁
let resizeTimer;
window.addEventListener('resize', function () {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(function () {
if (vantaEffect && typeof vantaEffect.resize === 'function') {
vantaEffect.resize();
}
}, 150);
});
}
// ==================== 載入畫面 ====================
function initLoader() {
const loader = document.getElementById('loader');
setTimeout(() => {
loader.classList.add('hidden');
setTimeout(() => {
loader.remove();
}, 500);
}, 2000);
}
// ==================== 花瓣飄落 ====================
function initPetals() {
const container = document.getElementById('globalPetalsContainer');
if (!container) return;
const isMobile = window.innerWidth < 768;
const maxPetals = isMobile ? 12 : 20;
let petalCount = 0;
const...