Files
ewoooc/templates/components/_loading.html
OoO 53edcc0077 refactor(templates): 統一模板目錄並移除 fallback loader
ADR-017 Phase 3f-4:根目錄模板搬入 templates/,補 trends/login_history,移除 ChoiceLoader 根目錄 fallback,搬移 components,刪除 web/templates 下的空檔/死檔與 compose 舊模板 mount。
2026-04-29 21:44:38 +08:00

338 lines
8.7 KiB
HTML
Executable File
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.
{#
WOOO 品牌載入動畫組件
使用方式:
1. 在頁面中 include 此組件:
{% include 'components/_loading.html' %}
2. 在 JavaScript 中控制顯示/隱藏:
showLoading('正在載入數據...') // 顯示
hideLoading() // 隱藏
3. 也可直接操作 DOM
document.getElementById('loadingOverlay').style.display = 'flex'; // 顯示
document.getElementById('loadingOverlay').style.display = 'none'; // 隱藏
#}
<!-- WOOO Loading Overlay -->
<div id="loadingOverlay" class="wooo-loading-overlay">
<div class="loading-logo-container">
<!-- 脈衝光暈 -->
<div class="logo-pulse"></div>
<!-- 外層旋轉光環 -->
<div class="logo-ring"></div>
<!-- 內層反向旋轉光環 -->
<div class="logo-ring-inner"></div>
<!-- 環繞粒子 -->
<div class="orbit-particles">
<div class="orbit-particle"></div>
<div class="orbit-particle"></div>
<div class="orbit-particle"></div>
<div class="orbit-particle"></div>
</div>
<!-- 閃爍星星 -->
<div class="sparkles">
<div class="sparkle"></div>
<div class="sparkle"></div>
<div class="sparkle"></div>
<div class="sparkle"></div>
<div class="sparkle"></div>
<div class="sparkle"></div>
</div>
<!-- LOGO -->
<div class="loading-logo">WOOO</div>
</div>
<div class="loading-text" id="loadingText">
<i class="fas fa-spinner fa-spin me-2"></i>正在載入數據...
</div>
<div class="loading-progress">
<div class="loading-progress-bar"></div>
</div>
<div class="loading-hint" id="loadingHint">
大量資料可能需要較長時間,請稍候
</div>
</div>
<style>
/* ============================================
WOOO 品牌載入動畫樣式
============================================ */
.wooo-loading-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(135deg, rgba(255, 255, 255, 0.95) 0%, rgba(240, 245, 255, 0.95) 100%);
z-index: 9999;
display: none;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 25px;
backdrop-filter: blur(8px);
}
/* LOGO 動畫容器 */
.wooo-loading-overlay .loading-logo-container {
position: relative;
width: 160px;
height: 160px;
display: flex;
justify-content: center;
align-items: center;
}
.wooo-loading-overlay .loading-logo {
z-index: 3;
animation: wooo-cloud-float 3s ease-in-out infinite;
font-size: 2.5rem;
font-weight: 800;
font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
background: linear-gradient(135deg, #4F46E5 0%, #7C3AED 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
letter-spacing: 4px;
filter: drop-shadow(0 4px 15px rgba(79, 70, 229, 0.4));
}
/* 雲端飄動動畫 */
@keyframes wooo-cloud-float {
0%, 100% {
transform: translateY(0) translateX(0) scale(1);
}
25% {
transform: translateY(-15px) translateX(5px) scale(1.02);
}
50% {
transform: translateY(-8px) translateX(-3px) scale(1);
}
75% {
transform: translateY(-20px) translateX(3px) scale(1.01);
}
}
/* 外層旋轉光環 */
.wooo-loading-overlay .logo-ring {
position: absolute;
width: 150px;
height: 150px;
border: 4px solid transparent;
border-top-color: #4F46E5;
border-right-color: #7C3AED;
border-radius: 50%;
animation: wooo-ring-spin 2s linear infinite;
}
/* 內層反向旋轉光環 */
.wooo-loading-overlay .logo-ring-inner {
position: absolute;
width: 120px;
height: 120px;
border: 3px solid transparent;
border-bottom-color: #EC4899;
border-left-color: #F59E0B;
border-radius: 50%;
animation: wooo-ring-spin-reverse 1.5s linear infinite;
}
/* 脈衝光暈 */
.wooo-loading-overlay .logo-pulse {
position: absolute;
width: 100px;
height: 100px;
background: radial-gradient(circle, rgba(79, 70, 229, 0.3) 0%, transparent 70%);
border-radius: 50%;
animation: wooo-pulse-expand 2s ease-out infinite;
}
@keyframes wooo-ring-spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
@keyframes wooo-ring-spin-reverse {
0% { transform: rotate(0deg); }
100% { transform: rotate(-360deg); }
}
@keyframes wooo-pulse-expand {
0% {
transform: scale(0.8);
opacity: 1;
}
100% {
transform: scale(1.8);
opacity: 0;
}
}
/* 環繞粒子 */
.wooo-loading-overlay .orbit-particles {
position: absolute;
width: 160px;
height: 160px;
animation: wooo-orbit-rotate 4s linear infinite;
}
.wooo-loading-overlay .orbit-particle {
position: absolute;
width: 8px;
height: 8px;
background: linear-gradient(135deg, #4F46E5, #7C3AED);
border-radius: 50%;
box-shadow: 0 0 10px rgba(79, 70, 229, 0.8);
}
.wooo-loading-overlay .orbit-particle:nth-child(1) {
top: 0;
left: 50%;
transform: translateX(-50%);
}
.wooo-loading-overlay .orbit-particle:nth-child(2) {
top: 50%;
right: 0;
transform: translateY(-50%);
}
.wooo-loading-overlay .orbit-particle:nth-child(3) {
bottom: 0;
left: 50%;
transform: translateX(-50%);
}
.wooo-loading-overlay .orbit-particle:nth-child(4) {
top: 50%;
left: 0;
transform: translateY(-50%);
}
@keyframes wooo-orbit-rotate {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* 閃爍星星 */
.wooo-loading-overlay .sparkles {
position: absolute;
width: 180px;
height: 180px;
}
.wooo-loading-overlay .sparkle {
position: absolute;
width: 4px;
height: 4px;
background: #FCD34D;
border-radius: 50%;
animation: wooo-sparkle-twinkle 1.5s ease-in-out infinite;
}
.wooo-loading-overlay .sparkle:nth-child(1) { top: 10%; left: 20%; animation-delay: 0s; }
.wooo-loading-overlay .sparkle:nth-child(2) { top: 5%; right: 25%; animation-delay: 0.3s; }
.wooo-loading-overlay .sparkle:nth-child(3) { bottom: 15%; right: 15%; animation-delay: 0.6s; }
.wooo-loading-overlay .sparkle:nth-child(4) { bottom: 10%; left: 25%; animation-delay: 0.9s; }
.wooo-loading-overlay .sparkle:nth-child(5) { top: 30%; left: 5%; animation-delay: 1.2s; }
.wooo-loading-overlay .sparkle:nth-child(6) { top: 25%; right: 5%; animation-delay: 0.4s; }
@keyframes wooo-sparkle-twinkle {
0%, 100% {
transform: scale(0);
opacity: 0;
}
50% {
transform: scale(1);
opacity: 1;
}
}
/* 載入文字 */
.wooo-loading-overlay .loading-text {
font-size: 1.2rem;
color: #4F46E5;
font-weight: 600;
text-align: center;
letter-spacing: 0.5px;
}
.wooo-loading-overlay .loading-hint {
font-size: 0.85rem;
color: #6b7280;
text-align: center;
max-width: 300px;
}
/* 進度條 */
.wooo-loading-overlay .loading-progress {
width: 200px;
height: 4px;
background: rgba(79, 70, 229, 0.2);
border-radius: 2px;
overflow: hidden;
}
.wooo-loading-overlay .loading-progress-bar {
height: 100%;
background: linear-gradient(90deg, #4F46E5, #7C3AED, #4F46E5);
background-size: 200% 100%;
animation: wooo-progress-flow 1.5s linear infinite;
width: 100%;
}
@keyframes wooo-progress-flow {
0% { background-position: 100% 0; }
100% { background-position: -100% 0; }
}
</style>
<script>
/**
* WOOO 載入動畫控制函數
*/
// 顯示載入動畫
function showLoading(text, hint) {
const overlay = document.getElementById('loadingOverlay');
const loadingText = document.getElementById('loadingText');
const loadingHint = document.getElementById('loadingHint');
if (text && loadingText) {
loadingText.innerHTML = '<i class="fas fa-spinner fa-spin me-2"></i>' + text;
}
if (hint && loadingHint) {
loadingHint.textContent = hint;
}
if (overlay) {
overlay.style.display = 'flex';
}
}
// 隱藏載入動畫
function hideLoading() {
const overlay = document.getElementById('loadingOverlay');
if (overlay) {
overlay.style.display = 'none';
}
}
// 更新載入文字
function updateLoadingText(text) {
const loadingText = document.getElementById('loadingText');
if (loadingText && text) {
loadingText.innerHTML = '<i class="fas fa-spinner fa-spin me-2"></i>' + text;
}
}
// 更新載入提示
function updateLoadingHint(hint) {
const loadingHint = document.getElementById('loadingHint');
if (loadingHint && hint) {
loadingHint.textContent = hint;
}
}
</script>