diff --git a/header.php b/header.php index f1355b2..ba93850 100644 --- a/header.php +++ b/header.php @@ -272,6 +272,9 @@ wp_enqueue_style("argon_css_merged", $GLOBALS['assets_path'] . "/assets/argon_css_merged.css", array(), $assets_version, 'all'); wp_enqueue_style("style", $GLOBALS['assets_path'] . "/style.css", array('argon_css_merged'), $assets_version, 'all'); + // 现代化布局和动画增强 + wp_enqueue_style("modern_enhancements", $GLOBALS['assets_path'] . "/modern-enhancements.css", array('style'), $assets_version, 'all'); + // 集成外部资源备用机制 wp_enqueue_script("resource_loader", $GLOBALS['assets_path'] . "/assets/vendor/external/resource-loader.js", array(), $assets_version, false); @@ -288,6 +291,9 @@ // 加载 argon_js_merged(包含 jQuery 和其他库)- 在头部同步加载以确保后续脚本可用 wp_enqueue_script("argon_js_merged", $GLOBALS['assets_path'] . "/assets/argon_js_merged.js", array(), $assets_version, false); + + // 现代化交互动画增强 - 在页面底部加载 + wp_enqueue_script("modern_enhancements", $GLOBALS['assets_path'] . "/modern-enhancements.js", array('argon_js_merged'), $assets_version, true); ?> diff --git a/modern-enhancements.css b/modern-enhancements.css new file mode 100644 index 0000000..9669723 --- /dev/null +++ b/modern-enhancements.css @@ -0,0 +1,903 @@ +/** + * Argon Theme - Modern UI Enhancements + * 现代化布局和动画优化 + * + * 特性: + * - Material Design 3 动画系统 + * - 桌面端悬停效果增强 + * - 移动端触摸反馈优化 + * - 滚动驱动动画 + * - 页面过渡效果 + */ + +/* ========== 1. 增强动画变量 ========== */ +:root { + /* 微交互时长 */ + --micro-duration: 80ms; + + /* 高级缓动函数 */ + --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1); + --ease-in-out-expo: cubic-bezier(0.87, 0, 0.13, 1); + --ease-elastic: cubic-bezier(0.68, -0.6, 0.32, 1.6); + --ease-back: cubic-bezier(0.34, 1.56, 0.64, 1); + + /* 阴影层级 - Material 3 */ + --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.05), 0 1px 3px rgba(0, 0, 0, 0.1); + --shadow-2: 0 2px 4px rgba(0, 0, 0, 0.05), 0 4px 8px rgba(0, 0, 0, 0.1); + --shadow-3: 0 4px 8px rgba(0, 0, 0, 0.05), 0 8px 16px rgba(0, 0, 0, 0.1); + --shadow-4: 0 8px 16px rgba(0, 0, 0, 0.08), 0 16px 32px rgba(0, 0, 0, 0.12); + --shadow-5: 0 12px 24px rgba(0, 0, 0, 0.1), 0 24px 48px rgba(0, 0, 0, 0.15); + + /* 悬停阴影 - 带主题色光晕 */ + --shadow-hover: 0 8px 25px rgba(0, 0, 0, 0.1), + 0 4px 10px rgba(var(--themecolor-rgbstr), 0.08); + --shadow-active: 0 2px 8px rgba(0, 0, 0, 0.08); +} + +html.darkmode { + --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.2), 0 1px 3px rgba(0, 0, 0, 0.3); + --shadow-2: 0 2px 4px rgba(0, 0, 0, 0.2), 0 4px 8px rgba(0, 0, 0, 0.3); + --shadow-3: 0 4px 8px rgba(0, 0, 0, 0.2), 0 8px 16px rgba(0, 0, 0, 0.3); + --shadow-4: 0 8px 16px rgba(0, 0, 0, 0.25), 0 16px 32px rgba(0, 0, 0, 0.35); + --shadow-5: 0 12px 24px rgba(0, 0, 0, 0.3), 0 24px 48px rgba(0, 0, 0, 0.4); + + --shadow-hover: 0 8px 25px rgba(0, 0, 0, 0.35), + 0 4px 10px rgba(var(--themecolor-rgbstr), 0.15); +} + +/* ========== 2. 桌面端卡片悬停效果增强 ========== */ +@media (hover: hover) and (pointer: fine) { + /* 文章卡片 - 高级悬停效果 */ + article.post.card { + transition: transform var(--animation-normal) var(--ease-out-expo), + box-shadow var(--animation-normal) var(--ease-standard); + will-change: transform, box-shadow; + } + + article.post.card:hover { + transform: translateY(-6px) scale(1.005); + box-shadow: var(--shadow-hover); + } + + article.post.card:active { + transform: translateY(-2px) scale(0.995); + box-shadow: var(--shadow-active); + transition-duration: var(--micro-duration); + } + + /* 缩略图悬停缩放 */ + article.post.card .post-thumbnail { + transition: transform var(--animation-slow) var(--ease-out-expo); + will-change: transform; + } + + article.post.card:hover .post-thumbnail { + transform: scale(1.05); + } + + /* 通用卡片悬停 */ + .card:not(article):not(.no-hover-effect) { + transition: transform var(--animation-normal) var(--ease-standard), + box-shadow var(--animation-normal) var(--ease-standard); + } + + .card:not(article):not(.no-hover-effect):hover { + transform: translateY(-3px); + box-shadow: var(--shadow-3); + } + + /* 侧边栏卡片悬停 */ + #leftbar .card, + #rightbar .card { + transition: transform var(--animation-normal) var(--ease-standard), + box-shadow var(--animation-normal) var(--ease-standard), + border-color var(--animation-fast) var(--ease-standard); + } + + #leftbar .card:hover, + #rightbar .card:hover { + transform: translateY(-2px); + box-shadow: var(--shadow-2); + border-color: rgba(var(--themecolor-rgbstr), 0.15); + } + + /* 按钮悬停效果增强 */ + .btn { + transition: all var(--animation-fast) var(--ease-standard); + position: relative; + overflow: hidden; + } + + .btn::after { + content: ""; + position: absolute; + inset: 0; + background: linear-gradient(180deg, rgba(255,255,255,0.15) 0%, transparent 100%); + opacity: 0; + transition: opacity var(--animation-fast) var(--ease-standard); + pointer-events: none; + } + + .btn:hover::after { + opacity: 1; + } + + .btn:hover { + transform: translateY(-1px); + } + + .btn:active { + transform: translateY(0) scale(0.98); + transition-duration: var(--micro-duration); + } + + /* 链接下划线动画 */ + article .post-content a:not([class*="button"]):not(.no-underline) { + background-image: linear-gradient(var(--themecolor), var(--themecolor)); + background-size: 0% 2px; + background-position: 0 100%; + background-repeat: no-repeat; + transition: background-size var(--animation-normal) var(--ease-out-expo); + } + + article .post-content a:not([class*="button"]):not(.no-underline):hover { + background-size: 100% 2px; + } + + /* 导航菜单项悬停 */ + .navbar-nav .nav-link { + position: relative; + transition: color var(--animation-fast) var(--ease-standard); + } + + .navbar-nav .nav-link::before { + content: ""; + position: absolute; + bottom: 0; + left: 50%; + width: 0; + height: 2px; + background: currentColor; + transition: width var(--animation-normal) var(--ease-out-expo), + left var(--animation-normal) var(--ease-out-expo); + border-radius: 1px; + } + + .navbar-nav .nav-link:hover::before { + width: 100%; + left: 0; + } + + /* 评论卡片悬停 */ + .comment-item { + transition: transform var(--animation-normal) var(--ease-standard), + box-shadow var(--animation-normal) var(--ease-standard); + } + + .comment-item:hover { + transform: translateX(4px); + box-shadow: -4px 0 0 var(--themecolor); + } +} + +/* ========== 3. 滚动入场动画 ========== */ +@keyframes fadeInUp { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes fadeInScale { + from { + opacity: 0; + transform: scale(0.95); + } + to { + opacity: 1; + transform: scale(1); + } +} + +@keyframes slideInLeft { + from { + opacity: 0; + transform: translateX(-20px); + } + to { + opacity: 1; + transform: translateX(0); + } +} + +@keyframes slideInRight { + from { + opacity: 0; + transform: translateX(20px); + } + to { + opacity: 1; + transform: translateX(0); + } +} + +/* 文章列表入场动画 */ +.article-list article.post { + animation: fadeInUp var(--animation-slow) var(--ease-emphasized-decelerate) both; +} + +.article-list article.post:nth-child(1) { animation-delay: 0ms; } +.article-list article.post:nth-child(2) { animation-delay: 50ms; } +.article-list article.post:nth-child(3) { animation-delay: 100ms; } +.article-list article.post:nth-child(4) { animation-delay: 150ms; } +.article-list article.post:nth-child(5) { animation-delay: 200ms; } +.article-list article.post:nth-child(6) { animation-delay: 250ms; } +.article-list article.post:nth-child(7) { animation-delay: 300ms; } +.article-list article.post:nth-child(8) { animation-delay: 350ms; } +.article-list article.post:nth-child(n+9) { animation-delay: 400ms; } + +/* 侧边栏入场动画 */ +#leftbar .card { + animation: slideInLeft var(--animation-slow) var(--ease-emphasized-decelerate) both; +} + +#leftbar .card:nth-child(1) { animation-delay: 100ms; } +#leftbar .card:nth-child(2) { animation-delay: 150ms; } +#leftbar .card:nth-child(3) { animation-delay: 200ms; } +#leftbar .card:nth-child(4) { animation-delay: 250ms; } +#leftbar .card:nth-child(5) { animation-delay: 300ms; } + +#rightbar .card { + animation: slideInRight var(--animation-slow) var(--ease-emphasized-decelerate) both; +} + +#rightbar .card:nth-child(1) { animation-delay: 100ms; } +#rightbar .card:nth-child(2) { animation-delay: 150ms; } +#rightbar .card:nth-child(3) { animation-delay: 200ms; } + +/* ========== 4. 页面过渡效果 ========== */ +/* PJAX 页面切换动画 */ +#primary.pjax-loading { + opacity: 0.6; + transform: translateY(10px); + pointer-events: none; +} + +#primary { + transition: opacity var(--animation-normal) var(--ease-standard), + transform var(--animation-normal) var(--ease-standard); +} + +/* 内容淡入效果 */ +@keyframes contentFadeIn { + from { + opacity: 0; + transform: translateY(15px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +article.post.post-full { + animation: contentFadeIn var(--animation-slow) var(--ease-emphasized-decelerate); +} + +/* ========== 5. 浮动按钮动画优化 ========== */ +#float_action_buttons { + transition: transform var(--animation-normal) var(--ease-back), + opacity var(--animation-normal) var(--ease-standard); +} + +#float_action_buttons .fabtn { + transition: transform var(--animation-fast) var(--ease-spring), + background var(--animation-fast) var(--ease-standard), + box-shadow var(--animation-fast) var(--ease-standard), + opacity var(--animation-normal) var(--ease-standard); +} + +@media (hover: hover) { + #float_action_buttons .fabtn:hover { + transform: scale(1.1); + box-shadow: var(--shadow-3); + } +} + +#float_action_buttons .fabtn:active { + transform: scale(0.9); + transition-duration: var(--micro-duration); +} + +/* 浮动按钮入场动画 */ +@keyframes fabtnBounceIn { + 0% { + opacity: 0; + transform: scale(0.3); + } + 50% { + transform: scale(1.05); + } + 70% { + transform: scale(0.95); + } + 100% { + opacity: 1; + transform: scale(1); + } +} + +#float_action_buttons:not(.fabtns-unloaded) .fabtn:not(.fabtn-hidden) { + animation: fabtnBounceIn var(--animation-slow) var(--ease-spring) both; +} + +#float_action_buttons .fabtn:nth-child(1) { animation-delay: 0ms; } +#float_action_buttons .fabtn:nth-child(2) { animation-delay: 50ms; } +#float_action_buttons .fabtn:nth-child(3) { animation-delay: 100ms; } +#float_action_buttons .fabtn:nth-child(4) { animation-delay: 150ms; } +#float_action_buttons .fabtn:nth-child(5) { animation-delay: 200ms; } + +/* ========== 6. 顶栏动画优化 ========== */ +#navbar-main { + transition: background-color var(--animation-normal) var(--ease-standard), + padding var(--animation-normal) var(--ease-standard), + box-shadow var(--animation-normal) var(--ease-standard), + transform var(--animation-normal) var(--ease-standard), + backdrop-filter var(--animation-normal) var(--ease-standard); +} + +/* 顶栏滚动效果 */ +#navbar-main:not(.navbar-ontop) { + box-shadow: var(--shadow-2); +} + +/* 搜索框展开动画 */ +#navbar_search_input_container .input-group { + transition: width var(--animation-normal) var(--ease-out-expo), + background var(--animation-fast) var(--ease-standard), + box-shadow var(--animation-fast) var(--ease-standard); +} + +#navbar_search_input_container.open .input-group { + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15); +} + +/* ========== 7. 评论区动画 ========== */ +.comment-item { + animation: fadeInUp var(--animation-normal) var(--ease-emphasized-decelerate) both; +} + +/* 评论交错入场 */ +.comment-item:nth-child(1) { animation-delay: 0ms; } +.comment-item:nth-child(2) { animation-delay: 30ms; } +.comment-item:nth-child(3) { animation-delay: 60ms; } +.comment-item:nth-child(4) { animation-delay: 90ms; } +.comment-item:nth-child(5) { animation-delay: 120ms; } +.comment-item:nth-child(n+6) { animation-delay: 150ms; } + +/* 评论发送成功动画 */ +@keyframes commentSuccess { + 0% { + transform: scale(0.8); + opacity: 0; + } + 50% { + transform: scale(1.02); + } + 100% { + transform: scale(1); + opacity: 1; + } +} + +.comment-item.new-comment { + animation: commentSuccess var(--animation-slow) var(--ease-spring); +} + +/* ========== 8. 图片加载动画 ========== */ +article img, +.post-thumbnail img { + transition: opacity var(--animation-normal) var(--ease-standard); +} + +article img[loading="lazy"], +.post-thumbnail img[loading="lazy"] { + opacity: 0; +} + +article img.loaded, +.post-thumbnail img.loaded, +article img:not([loading="lazy"]), +.post-thumbnail img:not([loading="lazy"]) { + opacity: 1; +} + +/* ========== 9. 表单元素动画 ========== */ +.form-control { + transition: border-color var(--animation-fast) var(--ease-standard), + box-shadow var(--animation-fast) var(--ease-standard), + background-color var(--animation-fast) var(--ease-standard); +} + +.form-control:focus { + box-shadow: 0 0 0 3px rgba(var(--themecolor-rgbstr), 0.15); + border-color: var(--themecolor); +} + +/* 输入框标签浮动效果 */ +.form-group.floating-label { + position: relative; +} + +.form-group.floating-label label { + position: absolute; + left: 12px; + top: 50%; + transform: translateY(-50%); + transition: all var(--animation-fast) var(--ease-standard); + pointer-events: none; + color: #999; + background: var(--color-foreground); + padding: 0 4px; +} + +.form-group.floating-label .form-control:focus ~ label, +.form-group.floating-label .form-control:not(:placeholder-shown) ~ label { + top: 0; + font-size: 12px; + color: var(--themecolor); +} + +/* ========== 10. 滚动条美化 ========== */ +::-webkit-scrollbar { + width: 8px; + height: 8px; +} + +::-webkit-scrollbar-track { + background: transparent; +} + +::-webkit-scrollbar-thumb { + background: rgba(var(--themecolor-rgbstr), 0.3); + border-radius: 4px; + border: 2px solid transparent; + background-clip: content-box; + transition: background var(--animation-fast) var(--ease-standard); +} + +::-webkit-scrollbar-thumb:hover { + background: rgba(var(--themecolor-rgbstr), 0.5); + background-clip: content-box; +} + +/* Firefox 滚动条 */ +* { + scrollbar-width: thin; + scrollbar-color: rgba(var(--themecolor-rgbstr), 0.3) transparent; +} + + +/* ========== 11. 移动端触摸优化 ========== */ +@media (hover: none) and (pointer: coarse) { + /* 移动端禁用悬停效果,优化触摸反馈 */ + article.post.card:hover { + transform: none; + box-shadow: var(--shadow-1); + } + + /* 触摸反馈 - 按下效果 */ + article.post.card:active { + transform: scale(0.98); + transition-duration: var(--micro-duration); + } + + .card:active { + transform: scale(0.99); + transition-duration: var(--micro-duration); + } + + /* 按钮触摸反馈 */ + .btn:active { + transform: scale(0.95); + transition-duration: var(--micro-duration); + } + + /* 链接触摸反馈 */ + a:active { + opacity: 0.7; + } + + /* 移动端点击高亮禁用 */ + * { + -webkit-tap-highlight-color: transparent; + } + + /* 触摸涟漪效果基础样式 */ + .touch-ripple { + position: absolute; + border-radius: 50%; + background: rgba(var(--themecolor-rgbstr), 0.25); + transform: scale(0); + animation: touchRipple 0.6s var(--ease-out-expo) forwards; + pointer-events: none; + } + + @keyframes touchRipple { + to { + transform: scale(4); + opacity: 0; + } + } +} + +/* ========== 12. 移动端侧边栏动画增强 ========== */ +@media screen and (max-width: 900px) { + /* 侧边栏滑入动画 */ + #leftbar { + transition: transform var(--animation-normal) var(--ease-out-expo), + box-shadow var(--animation-normal) var(--ease-standard); + transform: translateX(-100%); + box-shadow: none; + } + + html.leftbar-opened #leftbar { + transform: translateX(0); + box-shadow: 4px 0 25px rgba(0, 0, 0, 0.15); + } + + /* 遮罩层动画 */ + #leftbar_backdrop { + transition: opacity var(--animation-normal) var(--ease-standard), + visibility var(--animation-normal); + } + + /* 侧边栏内容入场动画 */ + html.leftbar-opened .leftbar-mobile-profile { + animation: slideInDown var(--animation-normal) var(--ease-emphasized-decelerate) 0.1s both; + } + + html.leftbar-opened .leftbar-mobile-search { + animation: fadeInUp var(--animation-normal) var(--ease-emphasized-decelerate) 0.15s both; + } + + html.leftbar-opened .leftbar-mobile-menu-section { + animation: fadeInUp var(--animation-normal) var(--ease-emphasized-decelerate) 0.2s both; + } + + html.leftbar-opened .leftbar-mobile-footer { + animation: fadeInUp var(--animation-normal) var(--ease-emphasized-decelerate) 0.25s both; + } + + @keyframes slideInDown { + from { + opacity: 0; + transform: translateY(-15px); + } + to { + opacity: 1; + transform: translateY(0); + } + } + + /* 移动端菜单项触摸反馈 */ + .leftbar-mobile-menu-item > a { + transition: background var(--animation-fast) var(--ease-standard), + transform var(--micro-duration) var(--ease-standard); + } + + .leftbar-mobile-menu-item > a:active { + background: rgba(var(--themecolor-rgbstr), 0.12); + transform: scale(0.98); + } + + /* 移动端底部导航栏(如果有) */ + .mobile-bottom-nav { + transition: transform var(--animation-normal) var(--ease-standard); + } + + .mobile-bottom-nav.hidden { + transform: translateY(100%); + } + + /* 移动端文章卡片优化 */ + article.post.card { + transition: transform var(--micro-duration) var(--ease-standard), + box-shadow var(--animation-fast) var(--ease-standard); + } + + article.post.card:active { + transform: scale(0.98); + } + + /* 移动端顶栏优化 */ + #navbar-main { + transition: transform var(--animation-normal) var(--ease-standard), + background-color var(--animation-fast) var(--ease-standard); + } + + /* 移动端搜索框展开 */ + #navbar_search_input_container { + transition: width var(--animation-normal) var(--ease-out-expo); + } +} + +/* ========== 13. 骨架屏加载动画 ========== */ +@keyframes skeletonPulse { + 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: skeletonPulse 1.5s ease-in-out infinite; + border-radius: var(--card-radius); +} + +/* ========== 14. 加载指示器 ========== */ +@keyframes spinnerRotate { + 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: spinnerRotate 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); +} + +/* ========== 15. 模态框/弹窗动画 ========== */ +.modal { + transition: opacity var(--animation-normal) var(--ease-standard); +} + +.modal.show { + opacity: 1; +} + +.modal-dialog { + transition: transform var(--animation-normal) var(--ease-emphasized-decelerate), + opacity var(--animation-normal) var(--ease-standard); + transform: scale(0.9) translateY(-20px); + opacity: 0; +} + +.modal.show .modal-dialog { + transform: scale(1) translateY(0); + opacity: 1; +} + +/* 底部弹出式模态框(移动端) */ +@media screen and (max-width: 900px) { + .modal-dialog.modal-bottom { + position: fixed; + bottom: 0; + left: 0; + right: 0; + margin: 0; + transform: translateY(100%); + border-radius: 20px 20px 0 0; + } + + .modal.show .modal-dialog.modal-bottom { + transform: translateY(0); + } +} + +/* ========== 16. 下拉菜单动画 ========== */ +.dropdown-menu { + opacity: 0; + transform: translateY(-10px) scale(0.95); + transform-origin: top center; + transition: opacity var(--animation-fast) var(--ease-standard), + transform var(--animation-fast) var(--ease-emphasized-decelerate), + visibility var(--animation-fast); + visibility: hidden; +} + +.dropdown-menu.show { + opacity: 1; + transform: translateY(0) scale(1); + visibility: visible; +} + +.dropdown-item { + transition: background var(--animation-fast) var(--ease-standard), + color var(--animation-fast) var(--ease-standard); +} + +/* ========== 17. 工具提示动画 ========== */ +.tooltip { + opacity: 0; + transform: translateY(5px); + transition: opacity var(--animation-fast) var(--ease-standard), + transform var(--animation-fast) var(--ease-emphasized-decelerate); +} + +.tooltip.show { + opacity: 1; + transform: translateY(0); +} + +/* ========== 18. 标签和徽章动画 ========== */ +.badge, +.tag { + transition: transform var(--animation-fast) var(--ease-spring), + background var(--animation-fast) var(--ease-standard); +} + +@media (hover: hover) { + .badge:hover, + .tag:hover { + transform: scale(1.05); + } +} + +.badge:active, +.tag:active { + transform: scale(0.95); +} + +/* ========== 19. 分页动画 ========== */ +.pagination .page-link { + transition: all var(--animation-fast) var(--ease-standard); +} + +@media (hover: hover) { + .pagination .page-link:hover { + transform: translateY(-2px); + box-shadow: var(--shadow-2); + } +} + +.pagination .page-link:active { + transform: translateY(0) scale(0.95); +} + +/* ========== 20. 目录导航动画 ========== */ +.index-link { + transition: all var(--animation-fast) var(--ease-standard); + position: relative; +} + +.index-link::before { + content: ""; + position: absolute; + left: -8px; + top: 50%; + transform: translateY(-50%) scaleY(0); + width: 3px; + height: 60%; + background: var(--themecolor); + border-radius: 2px; + transition: transform var(--animation-normal) var(--ease-spring); +} + +.index-item.current > .index-link::before { + transform: translateY(-50%) scaleY(1); +} + +/* ========== 21. 时间线动画 ========== */ +.timeline-item { + opacity: 0; + transform: translateX(-20px); + animation: timelineSlideIn var(--animation-slow) var(--ease-emphasized-decelerate) forwards; +} + +@keyframes timelineSlideIn { + to { + opacity: 1; + transform: translateX(0); + } +} + +.timeline-item:nth-child(1) { animation-delay: 0ms; } +.timeline-item:nth-child(2) { animation-delay: 100ms; } +.timeline-item:nth-child(3) { animation-delay: 200ms; } +.timeline-item:nth-child(4) { animation-delay: 300ms; } +.timeline-item:nth-child(5) { animation-delay: 400ms; } +.timeline-item:nth-child(n+6) { animation-delay: 500ms; } + +/* ========== 22. 友链卡片动画 ========== */ +.friend-link-item { + transition: transform var(--animation-normal) var(--ease-spring), + box-shadow var(--animation-normal) var(--ease-standard); +} + +@media (hover: hover) { + .friend-link-item:hover { + transform: translateY(-5px) rotate(1deg); + box-shadow: var(--shadow-4); + } + + .friend-link-item:hover .friend-link-avatar { + transform: scale(1.1) rotate(-5deg); + } +} + +.friend-link-avatar { + transition: transform var(--animation-normal) var(--ease-spring); +} + +/* ========== 23. 代码块动画 ========== */ +.hljs-codeblock { + transition: box-shadow var(--animation-normal) var(--ease-standard); +} + +@media (hover: hover) { + .hljs-codeblock:hover { + box-shadow: var(--shadow-3); + } +} + +/* 代码复制按钮 */ +.code-copy-btn { + opacity: 0; + transform: translateY(-5px); + transition: opacity var(--animation-fast) var(--ease-standard), + transform var(--animation-fast) var(--ease-standard), + background var(--animation-fast) var(--ease-standard); +} + +.hljs-codeblock:hover .code-copy-btn { + opacity: 1; + transform: translateY(0); +} + +/* ========== 24. 减少动画偏好支持 ========== */ +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + } + + /* 保留必要的过渡 */ + .card, + .btn, + a { + transition: none !important; + } +} + +/* ========== 25. 打印样式优化 ========== */ +@media print { + *, + *::before, + *::after { + animation: none !important; + transition: none !important; + } +} diff --git a/modern-enhancements.js b/modern-enhancements.js new file mode 100644 index 0000000..ea8b72b --- /dev/null +++ b/modern-enhancements.js @@ -0,0 +1,318 @@ +/** + * Argon Theme - Modern UI Enhancements JavaScript + * 现代化交互动画增强 + */ + +(function() { + 'use strict'; + + // ========== 1. 触摸涟漪效果 ========== + function createRipple(event, element) { + // 只在移动端或触摸设备上启用 + if (window.matchMedia('(hover: hover)').matches) return; + + const rect = element.getBoundingClientRect(); + const ripple = document.createElement('span'); + const size = Math.max(rect.width, rect.height); + + ripple.style.width = ripple.style.height = size + 'px'; + ripple.style.left = (event.clientX || event.touches[0].clientX) - rect.left - size / 2 + 'px'; + ripple.style.top = (event.clientY || event.touches[0].clientY) - rect.top - size / 2 + 'px'; + ripple.className = 'touch-ripple'; + + // 移除旧的涟漪 + const oldRipple = element.querySelector('.touch-ripple'); + if (oldRipple) oldRipple.remove(); + + element.style.position = 'relative'; + element.style.overflow = 'hidden'; + element.appendChild(ripple); + + // 动画结束后移除 + setTimeout(() => ripple.remove(), 600); + } + + // 为可点击元素添加涟漪效果 + function initRippleEffect() { + const rippleElements = document.querySelectorAll( + '.btn, .card, .nav-link, .dropdown-item, .page-link, ' + + '.leftbar-mobile-menu-item > a, .leftbar-mobile-action, ' + + '.fabtn, .comment-reply, .tag, .badge' + ); + + rippleElements.forEach(el => { + if (el.dataset.rippleInit) return; + el.dataset.rippleInit = 'true'; + + el.addEventListener('touchstart', function(e) { + createRipple(e, this); + }, { passive: true }); + }); + } + + // ========== 2. 图片加载动画 ========== + function initImageLoadAnimation() { + const images = document.querySelectorAll('article img[loading="lazy"], .post-thumbnail img'); + + images.forEach(img => { + if (img.dataset.loadAnimInit) return; + img.dataset.loadAnimInit = 'true'; + + if (img.complete) { + img.classList.add('loaded'); + } else { + img.addEventListener('load', function() { + this.classList.add('loaded'); + }); + } + }); + } + + // ========== 3. 滚动入场动画 (Intersection Observer) ========== + function initScrollAnimations() { + if (!('IntersectionObserver' in window)) return; + + const animatedElements = document.querySelectorAll( + '.article-list article.post, .comment-item, .timeline-item, ' + + '.friend-link-item, #leftbar .card, #rightbar .card' + ); + + const observer = new IntersectionObserver((entries) => { + entries.forEach(entry => { + if (entry.isIntersecting) { + entry.target.classList.add('animate-in'); + observer.unobserve(entry.target); + } + }); + }, { + threshold: 0.1, + rootMargin: '0px 0px -50px 0px' + }); + + animatedElements.forEach(el => { + if (!el.classList.contains('animate-in')) { + observer.observe(el); + } + }); + } + + // ========== 4. 平滑滚动增强 ========== + function initSmoothScroll() { + document.querySelectorAll('a[href^="#"]').forEach(anchor => { + if (anchor.dataset.smoothScrollInit) return; + anchor.dataset.smoothScrollInit = 'true'; + + anchor.addEventListener('click', function(e) { + const targetId = this.getAttribute('href'); + if (targetId === '#') return; + + const target = document.querySelector(targetId); + if (target) { + e.preventDefault(); + target.scrollIntoView({ + behavior: 'smooth', + block: 'start' + }); + } + }); + }); + } + + // ========== 5. 页面加载进度条 ========== + function initLoadingBar() { + // 检查是否已存在 + if (document.getElementById('page-loading-bar')) return; + + const bar = document.createElement('div'); + bar.id = 'page-loading-bar'; + bar.style.width = '0%'; + document.body.appendChild(bar); + + // 模拟加载进度 + let progress = 0; + const interval = setInterval(() => { + progress += Math.random() * 10; + if (progress >= 90) { + clearInterval(interval); + progress = 90; + } + bar.style.width = progress + '%'; + }, 100); + + // 页面加载完成 + window.addEventListener('load', () => { + clearInterval(interval); + bar.style.width = '100%'; + setTimeout(() => { + bar.style.opacity = '0'; + setTimeout(() => bar.remove(), 300); + }, 200); + }); + } + + // ========== 6. PJAX 加载动画 ========== + function initPjaxAnimations() { + if (typeof jQuery === 'undefined') return; + + jQuery(document).on('pjax:start', function() { + jQuery('#primary').addClass('pjax-loading'); + + // 显示加载进度条 + let bar = document.getElementById('page-loading-bar'); + if (!bar) { + bar = document.createElement('div'); + bar.id = 'page-loading-bar'; + document.body.appendChild(bar); + } + bar.style.opacity = '1'; + bar.style.width = '30%'; + + setTimeout(() => bar.style.width = '60%', 200); + }); + + jQuery(document).on('pjax:end', function() { + jQuery('#primary').removeClass('pjax-loading'); + + const bar = document.getElementById('page-loading-bar'); + if (bar) { + bar.style.width = '100%'; + setTimeout(() => { + bar.style.opacity = '0'; + setTimeout(() => bar.remove(), 300); + }, 200); + } + + // 重新初始化动画 + setTimeout(() => { + initRippleEffect(); + initImageLoadAnimation(); + initScrollAnimations(); + initSmoothScroll(); + }, 100); + }); + } + + // ========== 7. 卡片倾斜效果 (桌面端) ========== + function initCardTiltEffect() { + if (!window.matchMedia('(hover: hover)').matches) return; + + const cards = document.querySelectorAll('article.post.card'); + + cards.forEach(card => { + if (card.dataset.tiltInit) return; + card.dataset.tiltInit = 'true'; + + card.addEventListener('mousemove', function(e) { + const rect = this.getBoundingClientRect(); + const x = e.clientX - rect.left; + const y = e.clientY - rect.top; + const centerX = rect.width / 2; + const centerY = rect.height / 2; + + const rotateX = (y - centerY) / 20; + const rotateY = (centerX - x) / 20; + + this.style.transform = `perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) translateY(-6px)`; + }); + + card.addEventListener('mouseleave', function() { + this.style.transform = ''; + }); + }); + } + + // ========== 8. 浮动按钮显示/隐藏动画 ========== + function initFabAnimation() { + const fab = document.getElementById('float_action_buttons'); + if (!fab) return; + + let lastScrollY = window.scrollY; + let ticking = false; + + window.addEventListener('scroll', function() { + if (!ticking) { + window.requestAnimationFrame(function() { + const currentScrollY = window.scrollY; + + // 向下滚动时隐藏,向上滚动时显示 + if (currentScrollY > lastScrollY && currentScrollY > 300) { + fab.style.transform = 'translateY(100px)'; + fab.style.opacity = '0'; + } else { + fab.style.transform = ''; + fab.style.opacity = ''; + } + + lastScrollY = currentScrollY; + ticking = false; + }); + ticking = true; + } + }, { passive: true }); + } + + // ========== 9. 主题切换动画增强 ========== + function initThemeTransition() { + // 监听暗色模式切换 + const observer = new MutationObserver(function(mutations) { + mutations.forEach(function(mutation) { + if (mutation.attributeName === 'class') { + const html = document.documentElement; + if (html.classList.contains('darkmode') || !html.classList.contains('darkmode')) { + // 添加过渡类 + html.classList.add('theme-transitioning'); + setTimeout(() => { + html.classList.remove('theme-transitioning'); + }, 300); + } + } + }); + }); + + observer.observe(document.documentElement, { + attributes: true, + attributeFilter: ['class'] + }); + } + + // ========== 10. 减少动画偏好检测 ========== + function checkReducedMotion() { + if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) { + document.documentElement.classList.add('reduced-motion'); + } + } + + // ========== 初始化 ========== + function init() { + checkReducedMotion(); + initRippleEffect(); + initImageLoadAnimation(); + initScrollAnimations(); + initSmoothScroll(); + initPjaxAnimations(); + initThemeTransition(); + + // 桌面端特效 + if (window.matchMedia('(hover: hover)').matches) { + // initCardTiltEffect(); // 可选:卡片倾斜效果 + } + + // 移动端特效 + if (!window.matchMedia('(hover: hover)').matches) { + // initFabAnimation(); // 可选:浮动按钮滚动隐藏 + } + } + + // DOM 加载完成后初始化 + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', init); + } else { + init(); + } + + // 首次加载时显示进度条 + if (document.readyState !== 'complete') { + initLoadingBar(); + } + +})();