refactor: 重构加载动画代码,提升可维护性
JavaScript 重构: - 创建 LoadingOverlay 模块化管理器(IIFE 模式) - 封装元素创建、显示、隐藏和销毁逻辑 - 添加定时器管理,防止内存泄漏 - 提供向后兼容的函数接口 - 使用常量管理配置项(ID、类名、动画时长) - 改进代码注释和 JSDoc 文档 CSS 重构: - 统一类名前缀为 loading-*,语义更清晰 - 移除 ID 选择器依赖,改用类选择器 - 分离关注点:基础旋转器、进度条、遮罩层、骨架屏 - 添加结构化注释,便于定位和修改 - 优化选择器层级,提升性能 - 独立动画关键帧定义 代码改进: - 减少重复代码,提高复用性 - 更好的错误处理和边界情况处理 - 支持多次调用不会重复创建元素 - 清晰的模块边界和职责划分
This commit is contained in:
190
argontheme.js
190
argontheme.js
@@ -3199,73 +3199,167 @@ var pjaxContainers = pjaxContainerSelectors.filter(function(selector) {
|
|||||||
return document.querySelector(selector);
|
return document.querySelector(selector);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ==========================================================================
|
||||||
|
// 页面加载动画管理器
|
||||||
|
// ==========================================================================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 显示页面加载动画遮罩
|
* 加载动画管理器
|
||||||
|
* 负责创建、显示和隐藏页面加载动画
|
||||||
*/
|
*/
|
||||||
function showLoadingOverlay() {
|
const LoadingOverlay = (function() {
|
||||||
let el = document.getElementById('article-loading-overlay');
|
const OVERLAY_ID = 'article-loading-overlay';
|
||||||
if (!el) {
|
const ANIMATION_DURATION = 300;
|
||||||
// 动态创建加载动画元素
|
const CLASS_VISIBLE = 'is-visible';
|
||||||
el = document.createElement('div');
|
const CLASS_HIDING = 'is-hiding';
|
||||||
el.id = 'article-loading-overlay';
|
|
||||||
el.innerHTML = `
|
let overlayElement = null;
|
||||||
<div class="overlay-content">
|
let hideTimer = null;
|
||||||
<div class="overlay-card">
|
|
||||||
<div class="overlay-thumb skeleton">
|
/**
|
||||||
<div class="overlay-thumb-shimmer"></div>
|
* 创建骨架屏 HTML 结构
|
||||||
|
* @returns {string} HTML 字符串
|
||||||
|
*/
|
||||||
|
function createSkeletonHTML() {
|
||||||
|
return `
|
||||||
|
<div class="loading-overlay-content">
|
||||||
|
<div class="loading-card">
|
||||||
|
<div class="loading-thumb">
|
||||||
|
<div class="loading-shimmer"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="overlay-body">
|
<div class="loading-body">
|
||||||
<div class="overlay-meta">
|
<div class="loading-meta">
|
||||||
<div class="overlay-avatar skeleton"></div>
|
<div class="loading-avatar"></div>
|
||||||
<div class="overlay-meta-text">
|
<div class="loading-meta-text">
|
||||||
<div class="overlay-meta-line skeleton" style="width: 120px"></div>
|
<div class="loading-meta-line" style="width: 120px"></div>
|
||||||
<div class="overlay-meta-line skeleton" style="width: 80px"></div>
|
<div class="loading-meta-line" style="width: 80px"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="overlay-title skeleton"></div>
|
<div class="loading-title"></div>
|
||||||
<div class="overlay-text">
|
<div class="loading-text">
|
||||||
<div class="overlay-row skeleton" style="width: 95%"></div>
|
<div class="loading-line" style="width: 95%"></div>
|
||||||
<div class="overlay-row skeleton" style="width: 88%"></div>
|
<div class="loading-line" style="width: 88%"></div>
|
||||||
<div class="overlay-row skeleton" style="width: 92%"></div>
|
<div class="loading-line" style="width: 92%"></div>
|
||||||
<div class="overlay-row skeleton" style="width: 78%"></div>
|
<div class="loading-line" style="width: 78%"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="overlay-tags">
|
<div class="loading-tags">
|
||||||
<div class="overlay-tag skeleton"></div>
|
<div class="loading-tag"></div>
|
||||||
<div class="overlay-tag skeleton"></div>
|
<div class="loading-tag"></div>
|
||||||
<div class="overlay-tag skeleton"></div>
|
<div class="loading-tag"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="overlay-spinner">
|
<div class="loading-spinner-wrapper">
|
||||||
<div class="spinner-ring">
|
<div class="loading-spinner">
|
||||||
<div class="spinner-ring-inner"></div>
|
<div class="loading-spinner-ring"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="spinner-text">正在加载精彩内容</div>
|
<div class="loading-text-hint">正在加载精彩内容</div>
|
||||||
<div class="spinner-dots">
|
<div class="loading-dots">
|
||||||
<span class="dot"></span>
|
<span class="loading-dot"></span>
|
||||||
<span class="dot"></span>
|
<span class="loading-dot"></span>
|
||||||
<span class="dot"></span>
|
<span class="loading-dot"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
document.body.appendChild(el);
|
|
||||||
}
|
}
|
||||||
el.classList.remove('is-hiding');
|
|
||||||
el.classList.add('is-visible');
|
/**
|
||||||
|
* 创建加载动画元素
|
||||||
|
* @returns {HTMLElement} 创建的元素
|
||||||
|
*/
|
||||||
|
function createElement() {
|
||||||
|
const el = document.createElement('div');
|
||||||
|
el.id = OVERLAY_ID;
|
||||||
|
el.className = 'loading-overlay';
|
||||||
|
el.innerHTML = createSkeletonHTML();
|
||||||
|
return el;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取或创建加载动画元素
|
||||||
|
* @returns {HTMLElement} 加载动画元素
|
||||||
|
*/
|
||||||
|
function getElement() {
|
||||||
|
if (!overlayElement) {
|
||||||
|
overlayElement = document.getElementById(OVERLAY_ID);
|
||||||
|
}
|
||||||
|
if (!overlayElement) {
|
||||||
|
overlayElement = createElement();
|
||||||
|
document.body.appendChild(overlayElement);
|
||||||
|
}
|
||||||
|
return overlayElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示加载动画
|
||||||
|
*/
|
||||||
|
function show() {
|
||||||
|
// 清除可能存在的隐藏定时器
|
||||||
|
if (hideTimer) {
|
||||||
|
clearTimeout(hideTimer);
|
||||||
|
hideTimer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const el = getElement();
|
||||||
|
el.classList.remove(CLASS_HIDING);
|
||||||
|
|
||||||
|
// 强制重排以确保动画生效
|
||||||
|
void el.offsetWidth;
|
||||||
|
|
||||||
|
el.classList.add(CLASS_VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 隐藏加载动画
|
||||||
|
*/
|
||||||
|
function hide() {
|
||||||
|
const el = document.getElementById(OVERLAY_ID);
|
||||||
|
if (!el) return;
|
||||||
|
|
||||||
|
el.classList.add(CLASS_HIDING);
|
||||||
|
|
||||||
|
// 动画结束后清理状态
|
||||||
|
hideTimer = setTimeout(function() {
|
||||||
|
el.classList.remove(CLASS_VISIBLE, CLASS_HIDING);
|
||||||
|
hideTimer = null;
|
||||||
|
}, ANIMATION_DURATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 销毁加载动画元素
|
||||||
|
*/
|
||||||
|
function destroy() {
|
||||||
|
if (hideTimer) {
|
||||||
|
clearTimeout(hideTimer);
|
||||||
|
hideTimer = null;
|
||||||
|
}
|
||||||
|
if (overlayElement && overlayElement.parentNode) {
|
||||||
|
overlayElement.parentNode.removeChild(overlayElement);
|
||||||
|
overlayElement = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 公开 API
|
||||||
|
return {
|
||||||
|
show: show,
|
||||||
|
hide: hide,
|
||||||
|
destroy: destroy
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示页面加载动画(向后兼容)
|
||||||
|
*/
|
||||||
|
function showLoadingOverlay() {
|
||||||
|
LoadingOverlay.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 隐藏页面加载动画遮罩
|
* 隐藏页面加载动画(向后兼容)
|
||||||
*/
|
*/
|
||||||
function hideLoadingOverlay() {
|
function hideLoadingOverlay() {
|
||||||
let el = document.getElementById('article-loading-overlay');
|
LoadingOverlay.hide();
|
||||||
if (!el) return;
|
|
||||||
el.classList.add('is-hiding');
|
|
||||||
setTimeout(function() {
|
|
||||||
el.classList.remove('is-visible');
|
|
||||||
el.classList.remove('is-hiding');
|
|
||||||
}, 300);
|
|
||||||
}
|
}
|
||||||
function startPageTransition() {
|
function startPageTransition() {
|
||||||
document.documentElement.classList.add('page-transition-enter');
|
document.documentElement.classList.add('page-transition-enter');
|
||||||
@@ -3479,7 +3573,7 @@ $(document).on("click", ".reference-link , .reference-list-backlink" , function(
|
|||||||
}, 1);
|
}, 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
/*Tags Dialog pjax 加载后自动关闭/
|
/*Tags Dialog pjax 加载后自动关闭 */
|
||||||
$(document).on("click" , "#blog_tags .tag" , function(){
|
$(document).on("click" , "#blog_tags .tag" , function(){
|
||||||
$("#blog_tags button.close").trigger("click");
|
$("#blog_tags button.close").trigger("click");
|
||||||
});
|
});
|
||||||
|
|||||||
185
style.css
185
style.css
@@ -17047,13 +17047,39 @@ article img.loaded, .post-thumbnail img.loaded, article img:not([loading="lazy"]
|
|||||||
/* 11. 骨架屏和加载动画 */
|
/* 11. 骨架屏和加载动画 */
|
||||||
@keyframes modernSkeletonPulse { 0% { background-position: -200% 0; } 100% { background-position: 200% 0; } }
|
@keyframes modernSkeletonPulse { 0% { background-position: -200% 0; } 100% { background-position: 200% 0; } }
|
||||||
.skeleton { background: linear-gradient(90deg, var(--color-border-on-foreground) 25%, var(--color-border-on-foreground-deeper) 50%, var(--color-border-on-foreground) 75%); background-size: 200% 100%; animation: modernSkeletonPulse 1.5s ease-in-out infinite; border-radius: var(--card-radius); }
|
.skeleton { background: linear-gradient(90deg, var(--color-border-on-foreground) 25%, var(--color-border-on-foreground-deeper) 50%, var(--color-border-on-foreground) 75%); background-size: 200% 100%; animation: modernSkeletonPulse 1.5s ease-in-out infinite; border-radius: var(--card-radius); }
|
||||||
/* ---------- 加载动画 ---------- */
|
/* ==========================================================================
|
||||||
@keyframes modernSpinnerRotate { to { transform: rotate(360deg); } }
|
页面加载动画
|
||||||
.loading-spinner { width: 24px; height: 24px; border: 2px solid var(--color-border); border-top-color: var(--themecolor); border-radius: 50%; animation: modernSpinnerRotate 0.8s linear infinite; }
|
========================================================================== */
|
||||||
#page-loading-bar { position: fixed; top: 0; left: 0; height: 3px; background: var(--themecolor-gradient); z-index: 9999; transition: width var(--animation-fast) var(--ease-out-expo); box-shadow: 0 0 10px rgba(var(--themecolor-rgbstr), 0.5); }
|
|
||||||
|
|
||||||
/* 加载遮罩层 */
|
/* ---------- 基础旋转器 ---------- */
|
||||||
#article-loading-overlay {
|
@keyframes modernSpinnerRotate {
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.loading-spinner {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
border: 2px solid var(--color-border);
|
||||||
|
border-top-color: var(--themecolor);
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: modernSpinnerRotate 0.8s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------- 顶部进度条 ---------- */
|
||||||
|
#page-loading-bar {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 3px;
|
||||||
|
background: var(--themecolor-gradient);
|
||||||
|
z-index: 9999;
|
||||||
|
transition: width var(--animation-fast) var(--ease-out-expo);
|
||||||
|
box-shadow: 0 0 10px rgba(var(--themecolor-rgbstr), 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------- 加载遮罩层 ---------- */
|
||||||
|
.loading-overlay {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
z-index: 9998;
|
z-index: 9998;
|
||||||
@@ -17068,149 +17094,170 @@ article img.loaded, .post-thumbnail img.loaded, article img:not([loading="lazy"]
|
|||||||
-webkit-backdrop-filter: blur(var(--card-blur, 20px)) saturate(var(--card-saturate, 180%));
|
-webkit-backdrop-filter: blur(var(--card-blur, 20px)) saturate(var(--card-saturate, 180%));
|
||||||
backdrop-filter: blur(var(--card-blur, 20px)) saturate(var(--card-saturate, 180%));
|
backdrop-filter: blur(var(--card-blur, 20px)) saturate(var(--card-saturate, 180%));
|
||||||
}
|
}
|
||||||
html.darkmode #article-loading-overlay {
|
html.darkmode .loading-overlay {
|
||||||
background: rgba(0, 0, 0, 0.5);
|
background: rgba(0, 0, 0, 0.5);
|
||||||
}
|
}
|
||||||
#article-loading-overlay.is-visible {
|
.loading-overlay.is-visible {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
transition: opacity var(--animation-normal) var(--ease-standard), visibility 0s;
|
transition: opacity var(--animation-normal) var(--ease-standard), visibility 0s;
|
||||||
}
|
}
|
||||||
#article-loading-overlay.is-hiding {
|
.loading-overlay.is-hiding {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
transition: opacity var(--animation-normal) var(--ease-standard);
|
transition: opacity var(--animation-normal) var(--ease-standard);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 加载内容容器 */
|
/* ---------- 内容容器 ---------- */
|
||||||
#article-loading-overlay .overlay-content {
|
.loading-overlay-content {
|
||||||
width: min(720px, 90vw);
|
width: min(720px, 90vw);
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translate3d(0, 12px, 0) scale(0.98);
|
transform: translate3d(0, 12px, 0) scale(0.98);
|
||||||
transition: opacity var(--animation-normal) var(--ease-standard), transform var(--animation-normal) var(--ease-emphasized-decelerate);
|
transition: opacity var(--animation-normal) var(--ease-standard), transform var(--animation-normal) var(--ease-emphasized-decelerate);
|
||||||
}
|
}
|
||||||
#article-loading-overlay.is-visible .overlay-content {
|
.loading-overlay.is-visible .loading-overlay-content {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translate3d(0, 0, 0) scale(1);
|
transform: translate3d(0, 0, 0) scale(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 卡片容器 */
|
/* ---------- 卡片容器 ---------- */
|
||||||
#article-loading-overlay .overlay-card {
|
.loading-card {
|
||||||
background: var(--color-foreground);
|
background: var(--color-foreground);
|
||||||
border-radius: var(--card-radius);
|
border-radius: var(--card-radius);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08);
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08);
|
||||||
margin-bottom: 24px;
|
margin-bottom: 24px;
|
||||||
}
|
}
|
||||||
html.darkmode #article-loading-overlay .overlay-card {
|
html.darkmode .loading-card {
|
||||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 缩略图 */
|
/* ---------- 缩略图骨架 ---------- */
|
||||||
#article-loading-overlay .overlay-thumb {
|
.loading-thumb {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 240px;
|
height: 240px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
background: linear-gradient(90deg, var(--color-border-on-foreground) 25%, var(--color-border-on-foreground-deeper) 50%, var(--color-border-on-foreground) 75%);
|
||||||
|
background-size: 200% 100%;
|
||||||
|
animation: skeletonPulse 1.8s ease-in-out infinite;
|
||||||
}
|
}
|
||||||
#article-loading-overlay .overlay-thumb-shimmer {
|
.loading-shimmer {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: -100%;
|
left: -100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent);
|
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent);
|
||||||
animation: shimmer 2s infinite;
|
animation: shimmerMove 2s infinite;
|
||||||
}
|
}
|
||||||
html.darkmode #article-loading-overlay .overlay-thumb-shimmer {
|
html.darkmode .loading-shimmer {
|
||||||
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent);
|
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent);
|
||||||
}
|
}
|
||||||
@keyframes shimmer {
|
@keyframes shimmerMove {
|
||||||
to { left: 100%; }
|
to {
|
||||||
|
left: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes skeletonPulse {
|
||||||
|
0%, 100% {
|
||||||
|
background-position: 0% 0%;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
background-position: 100% 0%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 卡片主体 */
|
/* ---------- 卡片主体 ---------- */
|
||||||
#article-loading-overlay .overlay-body {
|
.loading-body {
|
||||||
padding: 24px;
|
padding: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 元信息区域 */
|
/* ---------- 元信息区域 ---------- */
|
||||||
#article-loading-overlay .overlay-meta {
|
.loading-meta {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
}
|
}
|
||||||
#article-loading-overlay .overlay-avatar {
|
.loading-avatar {
|
||||||
width: 40px;
|
width: 40px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
background: linear-gradient(90deg, var(--color-border-on-foreground) 25%, var(--color-border-on-foreground-deeper) 50%, var(--color-border-on-foreground) 75%);
|
||||||
|
background-size: 200% 100%;
|
||||||
|
animation: skeletonPulse 1.8s ease-in-out infinite;
|
||||||
}
|
}
|
||||||
#article-loading-overlay .overlay-meta-text {
|
.loading-meta-text {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
}
|
}
|
||||||
#article-loading-overlay .overlay-meta-line {
|
.loading-meta-line {
|
||||||
height: 12px;
|
height: 12px;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
|
background: linear-gradient(90deg, var(--color-border-on-foreground) 25%, var(--color-border-on-foreground-deeper) 50%, var(--color-border-on-foreground) 75%);
|
||||||
|
background-size: 200% 100%;
|
||||||
|
animation: skeletonPulse 1.8s ease-in-out infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 标题 */
|
/* ---------- 标题骨架 ---------- */
|
||||||
#article-loading-overlay .overlay-title {
|
.loading-title {
|
||||||
height: 28px;
|
height: 28px;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
border-radius: 14px;
|
border-radius: 14px;
|
||||||
width: 85%;
|
width: 85%;
|
||||||
|
background: linear-gradient(90deg, var(--color-border-on-foreground) 25%, var(--color-border-on-foreground-deeper) 50%, var(--color-border-on-foreground) 75%);
|
||||||
|
background-size: 200% 100%;
|
||||||
|
animation: skeletonPulse 1.8s ease-in-out infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 文本行 */
|
/* ---------- 文本行骨架 ---------- */
|
||||||
#article-loading-overlay .overlay-text {
|
.loading-text {
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
}
|
}
|
||||||
#article-loading-overlay .overlay-row {
|
.loading-line {
|
||||||
height: 14px;
|
height: 14px;
|
||||||
margin: 8px 0;
|
margin: 8px 0;
|
||||||
border-radius: 7px;
|
border-radius: 7px;
|
||||||
|
background: linear-gradient(90deg, var(--color-border-on-foreground) 25%, var(--color-border-on-foreground-deeper) 50%, var(--color-border-on-foreground) 75%);
|
||||||
|
background-size: 200% 100%;
|
||||||
|
animation: skeletonPulse 1.8s ease-in-out infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 标签 */
|
/* ---------- 标签骨架 ---------- */
|
||||||
#article-loading-overlay .overlay-tags {
|
.loading-tags {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
#article-loading-overlay .overlay-tag {
|
.loading-tag {
|
||||||
width: 60px;
|
width: 60px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
}
|
|
||||||
|
|
||||||
/* 骨架屏动画 */
|
|
||||||
#article-loading-overlay .skeleton {
|
|
||||||
background: linear-gradient(90deg, var(--color-border-on-foreground) 25%, var(--color-border-on-foreground-deeper) 50%, var(--color-border-on-foreground) 75%);
|
background: linear-gradient(90deg, var(--color-border-on-foreground) 25%, var(--color-border-on-foreground-deeper) 50%, var(--color-border-on-foreground) 75%);
|
||||||
background-size: 200% 100%;
|
background-size: 200% 100%;
|
||||||
animation: modernSkeletonPulse 1.8s ease-in-out infinite;
|
animation: skeletonPulse 1.8s ease-in-out infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 加载旋转器 */
|
/* ---------- 加载旋转器 ---------- */
|
||||||
#article-loading-overlay .overlay-spinner {
|
.loading-spinner-wrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
#article-loading-overlay .spinner-ring {
|
.loading-spinner {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 56px;
|
width: 56px;
|
||||||
height: 56px;
|
height: 56px;
|
||||||
}
|
}
|
||||||
#article-loading-overlay .spinner-ring::before {
|
.loading-spinner::before {
|
||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
@@ -17218,7 +17265,7 @@ html.darkmode #article-loading-overlay .overlay-thumb-shimmer {
|
|||||||
border: 3px solid var(--color-border);
|
border: 3px solid var(--color-border);
|
||||||
opacity: 0.2;
|
opacity: 0.2;
|
||||||
}
|
}
|
||||||
#article-loading-overlay .spinner-ring-inner {
|
.loading-spinner-ring {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
@@ -17228,34 +17275,38 @@ html.darkmode #article-loading-overlay .overlay-thumb-shimmer {
|
|||||||
animation: spinnerRotate 1s cubic-bezier(0.68, -0.55, 0.265, 1.55) infinite;
|
animation: spinnerRotate 1s cubic-bezier(0.68, -0.55, 0.265, 1.55) infinite;
|
||||||
}
|
}
|
||||||
@keyframes spinnerRotate {
|
@keyframes spinnerRotate {
|
||||||
0% { transform: rotate(0deg); }
|
0% {
|
||||||
100% { transform: rotate(360deg); }
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 加载文字 */
|
/* ---------- 加载文字 ---------- */
|
||||||
#article-loading-overlay .spinner-text {
|
.loading-text-hint {
|
||||||
color: var(--color-font);
|
color: var(--color-font);
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
letter-spacing: 0.3px;
|
letter-spacing: 0.3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 加载点动画 */
|
/* ---------- 加载点动画 ---------- */
|
||||||
#article-loading-overlay .spinner-dots {
|
.loading-dots {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
}
|
}
|
||||||
#article-loading-overlay .spinner-dots .dot {
|
.loading-dot {
|
||||||
width: 6px;
|
width: 6px;
|
||||||
height: 6px;
|
height: 6px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background: var(--themecolor);
|
background: var(--themecolor);
|
||||||
animation: dotBounce 1.4s infinite ease-in-out both;
|
animation: dotBounce 1.4s infinite ease-in-out both;
|
||||||
}
|
}
|
||||||
#article-loading-overlay .spinner-dots .dot:nth-child(1) {
|
.loading-dot:nth-child(1) {
|
||||||
animation-delay: -0.32s;
|
animation-delay: -0.32s;
|
||||||
}
|
}
|
||||||
#article-loading-overlay .spinner-dots .dot:nth-child(2) {
|
.loading-dot:nth-child(2) {
|
||||||
animation-delay: -0.16s;
|
animation-delay: -0.16s;
|
||||||
}
|
}
|
||||||
@keyframes dotBounce {
|
@keyframes dotBounce {
|
||||||
@@ -17269,40 +17320,40 @@ html.darkmode #article-loading-overlay .overlay-thumb-shimmer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 响应式适配 */
|
/* ---------- 响应式适配 ---------- */
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
#article-loading-overlay .overlay-thumb {
|
.loading-thumb {
|
||||||
height: 180px;
|
height: 180px;
|
||||||
}
|
}
|
||||||
#article-loading-overlay .overlay-body {
|
.loading-body {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
#article-loading-overlay .overlay-title {
|
.loading-title {
|
||||||
height: 24px;
|
height: 24px;
|
||||||
width: 90%;
|
width: 90%;
|
||||||
}
|
}
|
||||||
#article-loading-overlay .spinner-ring {
|
.loading-spinner {
|
||||||
width: 48px;
|
width: 48px;
|
||||||
height: 48px;
|
height: 48px;
|
||||||
}
|
}
|
||||||
#article-loading-overlay .spinner-text {
|
.loading-text-hint {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@media (max-width: 480px) {
|
@media (max-width: 480px) {
|
||||||
#article-loading-overlay .overlay-content {
|
.loading-overlay-content {
|
||||||
width: 95vw;
|
width: 95vw;
|
||||||
}
|
}
|
||||||
#article-loading-overlay .overlay-thumb {
|
.loading-thumb {
|
||||||
height: 160px;
|
height: 160px;
|
||||||
}
|
}
|
||||||
#article-loading-overlay .overlay-body {
|
.loading-body {
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
}
|
}
|
||||||
#article-loading-overlay .overlay-meta {
|
.loading-meta {
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
}
|
}
|
||||||
#article-loading-overlay .overlay-avatar {
|
.loading-avatar {
|
||||||
width: 36px;
|
width: 36px;
|
||||||
height: 36px;
|
height: 36px;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user