diff --git a/frontend/index.html b/frontend/index.html
index 03d7d18..f3e79f0 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -209,11 +209,97 @@
.code-block-wrapper .hljs-meta {
color: #58a6ff !important; /* 天蓝元数据 */
}
+
+ /* ================= 鼠标响应式交互特效 (Linear / Vercel 风格) ================= */
+ /* 1. 聚光灯卡片边缘与表面流光跟随 */
+ .spotlight-card {
+ position: relative;
+ overflow: hidden;
+ transition: transform 0.25s cubic-bezier(0.2, 0.8, 0.2, 1), box-shadow 0.25s ease, border-color 0.25s ease;
+ }
+ .spotlight-card::before {
+ content: '';
+ position: absolute;
+ inset: 0;
+ border-radius: inherit;
+ background: radial-gradient(450px circle at var(--mouse-x, -999px) var(--mouse-y, -999px), rgba(14, 165, 233, 0.14), transparent 75%);
+ opacity: 0;
+ transition: opacity 0.3s ease;
+ pointer-events: none;
+ z-index: 1;
+ }
+ .dark .spotlight-card::before {
+ background: radial-gradient(450px circle at var(--mouse-x, -999px) var(--mouse-y, -999px), rgba(56, 189, 248, 0.22), rgba(99, 102, 241, 0.1) 45%, transparent 75%);
+ }
+ .spotlight-card:hover::before {
+ opacity: 1;
+ }
+
+ /* 2. 3D 视差微倾斜容器 */
+ .tilt-card {
+ transform-style: preserve-3d;
+ transition: transform 0.12s ease-out;
+ will-change: transform;
+ }
+
+ /* 3. 极客光标跟随光圈与准星光点 (仅桌面鼠标端启用) */
+ .cursor-follower {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 36px;
+ height: 36px;
+ border-radius: 9999px;
+ border: 1.5px solid rgba(56, 189, 248, 0.45);
+ background: rgba(56, 189, 248, 0.05);
+ pointer-events: none;
+ z-index: 9999;
+ transform: translate(-50%, -50%);
+ transition: width 0.2s cubic-bezier(0.2, 0.8, 0.2, 1), height 0.2s cubic-bezier(0.2, 0.8, 0.2, 1), border-color 0.2s, background-color 0.2s;
+ display: none;
+ backdrop-filter: blur(0.5px);
+ }
+ @media (hover: hover) and (pointer: fine) {
+ .cursor-follower { display: block; }
+ }
+ .cursor-follower.hovering {
+ width: 58px;
+ height: 58px;
+ border-color: rgba(99, 102, 241, 0.75);
+ background: rgba(99, 102, 241, 0.1);
+ }
+ .cursor-dot {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 6px;
+ height: 6px;
+ border-radius: 9999px;
+ background: #38bdf8;
+ pointer-events: none;
+ z-index: 10000;
+ transform: translate(-50%, -50%);
+ box-shadow: 0 0 10px #38bdf8;
+ display: none;
+ }
+ @media (hover: hover) and (pointer: fine) {
+ .cursor-dot { display: block; }
+ }
-
+
+
+
+
+
+
+
+
+
-
-
+
+
@@ -480,7 +566,7 @@
+ class="spotlight-card group p-6 sm:p-7 rounded-3xl bg-white dark:bg-slate-900 border border-slate-200/80 dark:border-slate-800 shadow-sm hover:shadow-xl hover:border-sky-500/40 dark:hover:border-sky-500/40 transition-all duration-300 cursor-pointer relative overflow-hidden">
@@ -805,7 +891,7 @@
+ class="spotlight-card p-6 rounded-3xl bg-white dark:bg-slate-900 border border-slate-200/80 dark:border-slate-800 hover:border-sky-500/50 shadow-sm hover:shadow-xl transition-all cursor-pointer group">
{{ cat.icon }}
@@ -2091,6 +2177,9 @@
});
}
+ // 启动 Linear / Vercel 鼠标跟随响应交互系统
+ initMouseEffects();
+
window.addEventListener('scroll', handleScroll);
window.addEventListener('hashchange', handleHashRoute);
@@ -2100,6 +2189,83 @@
handleHashRoute();
});
+ // ============ 鼠标响应式交互系统核心驱动 (Linear / Vercel 风格) ============
+ function initMouseEffects() {
+ const ambient = document.getElementById('ambient-cursor');
+ const follower = document.getElementById('cursor-follower');
+ const dot = document.getElementById('cursor-dot');
+
+ let mouseX = window.innerWidth / 2;
+ let mouseY = window.innerHeight / 2;
+ let ambX = mouseX, ambY = mouseY;
+ let folX = mouseX, folY = mouseY;
+
+ window.addEventListener('mousemove', (e) => {
+ mouseX = e.clientX;
+ mouseY = e.clientY;
+
+ if (dot) {
+ dot.style.left = `${mouseX}px`;
+ dot.style.top = `${mouseY}px`;
+ }
+
+ // 聚光灯流光跟随计算
+ const cards = document.querySelectorAll('.spotlight-card');
+ cards.forEach(card => {
+ const rect = card.getBoundingClientRect();
+ if (mouseX >= rect.left - 120 && mouseX <= rect.right + 120 &&
+ mouseY >= rect.top - 120 && mouseY <= rect.bottom + 120) {
+ const x = mouseX - rect.left;
+ const y = mouseY - rect.top;
+ card.style.setProperty('--mouse-x', `${x}px`);
+ card.style.setProperty('--mouse-y', `${y}px`);
+ }
+ });
+
+ // 3D 陀螺仪视差倾斜
+ const tiltCards = document.querySelectorAll('.tilt-card');
+ tiltCards.forEach(card => {
+ const rect = card.getBoundingClientRect();
+ if (mouseX >= rect.left && mouseX <= rect.right && mouseY >= rect.top && mouseY <= rect.bottom) {
+ const normX = (mouseX - rect.left) / rect.width - 0.5;
+ const normY = (mouseY - rect.top) / rect.height - 0.5;
+ card.style.transform = `perspective(1000px) rotateY(${normX * 6}deg) rotateX(${-normY * 6}deg) translateY(-2px)`;
+ } else {
+ card.style.transform = 'perspective(1000px) rotateY(0deg) rotateX(0deg) translateY(0px)';
+ }
+ });
+ });
+
+ // 交互悬停扩圈检测
+ document.addEventListener('mouseover', (e) => {
+ if (e.target.closest('a, button, input, textarea, select, .spotlight-card, [role="button"]')) {
+ follower?.classList.add('hovering');
+ } else {
+ follower?.classList.remove('hovering');
+ }
+ });
+
+ // 60FPS 平滑阻尼插值渲染 (Lerp)
+ function renderLoop() {
+ ambX += (mouseX - ambX) * 0.05;
+ ambY += (mouseY - ambY) * 0.05;
+ if (ambient) {
+ ambient.style.left = `${ambX}px`;
+ ambient.style.top = `${ambY}px`;
+ }
+
+ folX += (mouseX - folX) * 0.2;
+ folY += (mouseY - folY) * 0.2;
+ if (follower) {
+ follower.style.left = `${folX}px`;
+ follower.style.top = `${folY}px`;
+ }
+
+ requestAnimationFrame(renderLoop);
+ }
+ requestAnimationFrame(renderLoop);
+ }
+
onUnmounted(() => {
window.removeEventListener('scroll', handleScroll);
window.removeEventListener('hashchange', handleHashRoute);