diff --git a/web/dist/shop/index.html b/web/dist/shop/index.html index fb33bb0..2af5138 100644 --- a/web/dist/shop/index.html +++ b/web/dist/shop/index.html @@ -233,6 +233,21 @@ img { max-width:100%; display:block; } .products-grid { grid-template-columns:1fr; } .hero-content h1 { font-size:24px; } } + +/* ========== 3D 动态效果 & 鼠标光影(新增)========== */ +/* 鼠标跟随光斑 */ +.cursor-glow{position:fixed;width:600px;height:600px;border-radius:50%;background:radial-gradient(circle,rgba(230,57,70,0.12) 0%,transparent 70%);pointer-events:none;z-index:150;transform:translate(-50%,-50%);transition:opacity .3s;mix-blend-mode:multiply;opacity:0;left:0;top:0} +.cursor-glow.active{opacity:1} +/* 3D 卡片容器与倾斜 */ +.products-grid{perspective:1000px} +.product-card{transform-style:preserve-3d;transition:transform .15s ease-out,box-shadow .25s} +.product-card .product-image{transform:translateZ(20px)} +.product-card .product-info{transform:translateZ(15px)} +/* 卡片表面光影反射(玻璃高光) */ +.product-card::after{content:'';position:absolute;inset:0;border-radius:inherit;background:radial-gradient(circle at var(--mx,50%) var(--my,50%),rgba(255,255,255,0.25) 0%,transparent 50%);opacity:0;transition:opacity .3s;pointer-events:none;z-index:2} +.product-card:hover::after{opacity:1} +/* 触摸设备隐藏光斑 */ +@media (hover:none){.cursor-glow{display:none !important}} @@ -811,6 +826,81 @@ async function init() { } init(); + +// ========== 3D 动态效果 & 鼠标光影(新增)========== +(function(){ + var isTouch = window.matchMedia('(hover: none)').matches; + + /* ----- 鼠标跟随光斑 ----- */ + var cursorGlow = document.createElement('div'); + cursorGlow.className = 'cursor-glow'; + document.body.appendChild(cursorGlow); + if (!isTouch) { + var glowOn = false; + document.addEventListener('mousemove', function(e){ + cursorGlow.style.left = e.clientX + 'px'; + cursorGlow.style.top = e.clientY + 'px'; + if (!glowOn) { cursorGlow.classList.add('active'); glowOn = true; } + }); + document.addEventListener('mouseleave', function(){ + cursorGlow.classList.remove('active'); glowOn = false; + }); + } + + /* ----- 产品卡片 3D 倾斜 + 表面高光 ----- */ + if (!isTouch) { + var tiltRaf = null, tiltEvt = null; + function tiltUpdate(){ + tiltRaf = null; + var e = tiltEvt; + if (!e) return; + var cards = document.querySelectorAll('.product-card'); + for (var i = 0; i < cards.length; i++) { + var card = cards[i]; + var rect = card.getBoundingClientRect(); + if (e.clientX < rect.left || e.clientX > rect.right || e.clientY < rect.top || e.clientY > rect.bottom) continue; + var cx = rect.left + rect.width / 2; + var cy = rect.top + rect.height / 2; + var rx = ((e.clientY - cy) / rect.height) * -8; + var ry = ((e.clientX - cx) / rect.width) * 8; + card.style.transform = 'perspective(1000px) rotateX(' + rx + 'deg) rotateY(' + ry + 'deg) translateY(-4px)'; + card.style.setProperty('--mx', ((e.clientX - rect.left) / rect.width * 100) + '%'); + card.style.setProperty('--my', ((e.clientY - rect.top) / rect.height * 100) + '%'); + } + } + document.addEventListener('mousemove', function(e){ + tiltEvt = e; + if (tiltRaf === null) tiltRaf = requestAnimationFrame(tiltUpdate); + }); + // 鼠标真正离开卡片时恢复(relatedTarget 仍在卡片内则保持倾斜,避免子元素间移动闪烁) + document.addEventListener('mouseout', function(e){ + var t = e.target; + if (t && t.classList && t.classList.contains('product-card')) { + var r = e.relatedTarget; + if (r && (r === t || t.contains(r))) return; + t.style.transform = ''; + } + }); + } + + /* ----- Hero 区域 3D 视差 ----- */ + if (!isTouch) { + var heroContent = document.querySelector('.hero-content'); + var heroRaf = null, heroEvt = null; + function heroUpdate(){ + heroRaf = null; + var e = heroEvt; + if (!e || !heroContent) return; + var x = (e.clientX / window.innerWidth - 0.5) * 2; + var y = (e.clientY / window.innerHeight - 0.5) * 2; + heroContent.style.transform = 'translate(' + (x * 10) + 'px,' + (y * 10) + 'px)'; + } + document.addEventListener('mousemove', function(e){ + heroEvt = e; + if (heroRaf === null) heroRaf = requestAnimationFrame(heroUpdate); + }); + } +})(); diff --git a/web/dist/shop2/index.html b/web/dist/shop2/index.html index 1d22edb..ea5260f 100644 --- a/web/dist/shop2/index.html +++ b/web/dist/shop2/index.html @@ -1217,6 +1217,59 @@ body::before { .hero-content h1 { font-size:30px; } .hero-stats { flex-wrap:wrap; gap:16px; } } + +/* ========== 3D 动态效果 & 鼠标光影(新增) ========== */ +/* 鼠标霓虹光斑:固定跟随鼠标,紫青混合,screen 混合在暗色背景上发光 */ +.cursor-glow { + position: fixed; + width: 500px; + height: 500px; + border-radius: 50%; + background: radial-gradient(circle, rgba(191,90,242,0.15) 0%, rgba(100,210,255,0.08) 40%, transparent 70%); + pointer-events: none; + z-index: 150; + transform: translate(-50%, -50%); + mix-blend-mode: screen; + filter: blur(20px); + left: 50vw; + top: 50vh; +} + +/* 3D 卡片倾斜容器 */ +.products-grid { perspective: 1200px; } +.product-card { transform-style: preserve-3d; transition: transform .15s ease-out, box-shadow .3s; } +.product-card:hover { box-shadow: 0 0 30px rgba(191,90,242,0.3), 0 8px 40px rgba(0,0,0,0.5); } +.product-card .product-image { transform: translateZ(25px); } +.product-card .product-info { transform: translateZ(15px); } + +/* 卡片表面霓虹高光反射(随鼠标位置移动) */ +.product-card::after { + content: ''; + position: absolute; + inset: 0; + border-radius: inherit; + background: radial-gradient(circle at var(--mx, 50%) var(--my, 50%), rgba(191,90,242,0.2) 0%, transparent 50%); + opacity: 0; + transition: opacity .3s; + pointer-events: none; + z-index: 3; +} +.product-card:hover::after { opacity: 1; } + +/* 浮动霓虹粒子背景 */ +.neon-particle { + position: fixed; + width: 4px; + height: 4px; + border-radius: 50%; + pointer-events: none; + z-index: 1; + animation: float-particle 20s infinite ease-in-out; +} +@keyframes float-particle { + 0%, 100% { transform: translate(0, 0); opacity: 0.3; } + 50% { transform: translate(30px, -50px); opacity: 0.8; } +} @@ -1917,6 +1970,50 @@ async function init() { } init(); + +// ========== 3D 动态效果 & 鼠标光影(新增) ========== +// 鼠标霓虹光斑跟随 +const cursorGlow = document.createElement('div'); +cursorGlow.className = 'cursor-glow'; +cursorGlow.style.left = '50vw'; +cursorGlow.style.top = '50vh'; +document.body.appendChild(cursorGlow); +document.addEventListener('mousemove', e => { + cursorGlow.style.left = e.clientX + 'px'; + cursorGlow.style.top = e.clientY + 'px'; +}); + +// 产品卡片 3D 倾斜 + 表面霓虹高光(鼠标在卡片上时倾斜,离开时恢复) +document.addEventListener('mousemove', e => { + document.querySelectorAll('.product-card').forEach(card => { + const rect = card.getBoundingClientRect(); + if (e.clientX >= rect.left && e.clientX <= rect.right && e.clientY >= rect.top && e.clientY <= rect.bottom) { + const cx = rect.left + rect.width / 2; + const cy = rect.top + rect.height / 2; + const rx = ((e.clientY - cy) / rect.height) * -10; + const ry = ((e.clientX - cx) / rect.width) * 10; + card.style.transform = `perspective(1200px) rotateX(${rx}deg) rotateY(${ry}deg) translateY(-4px)`; + card.style.setProperty('--mx', ((e.clientX - rect.left) / rect.width * 100) + '%'); + card.style.setProperty('--my', ((e.clientY - rect.top) / rect.height * 100) + '%'); + } else if (card.style.transform) { + card.style.transform = ''; + } + }); +}); + +// 创建霓虹浮动粒子(12 个,紫/青/粉/绿随机分布) +const particleColors = ['#BF5AF2', '#64D2FF', '#FF375F', '#30D158']; +for (let i = 0; i < 12; i++) { + const p = document.createElement('div'); + p.className = 'neon-particle'; + p.style.left = Math.random() * 100 + 'vw'; + p.style.top = Math.random() * 100 + 'vh'; + p.style.background = particleColors[i % 4]; + p.style.boxShadow = '0 0 8px ' + particleColors[i % 4]; + p.style.animationDuration = (15 + Math.random() * 15) + 's'; + p.style.animationDelay = -Math.random() * 20 + 's'; + document.body.appendChild(p); +} diff --git a/web/dist/shop3/index.html b/web/dist/shop3/index.html index d539bb4..8aad540 100644 --- a/web/dist/shop3/index.html +++ b/web/dist/shop3/index.html @@ -883,6 +883,71 @@ input { font-family: inherit; outline: none; } .toolbar { flex-direction: column; align-items: flex-start; } .modal-meta { grid-template-columns: 1fr 1fr 1fr; } } + +/* ========== 3D 动效 & 鼠标光影(北欧极简 · 克制优雅)========== */ + +/* 全局鼠标跟随柔光斑(灰粉 → 灰绿 → 透明,multiply 柔和叠加)*/ +.cursor-glow{ + position:fixed; + top:0; left:0; + width:500px; height:500px; + border-radius:50%; + background:radial-gradient(circle, rgba(212,165,165,0.10) 0%, rgba(168,197,160,0.06) 40%, transparent 70%); + pointer-events:none; + z-index:150; /* 高于导航栏(100),低于所有弹窗(180+) */ + transform:translate(-50%,-50%); + mix-blend-mode:multiply; + filter:blur(10px); + will-change:transform; +} + +/* 3D 透视容器 */ +.products-grid{ perspective:1000px; } +.featured-grid{ perspective:1000px; } + +/* 卡片 3D 倾斜基础(preserve-3d + 柔和过渡)*/ +.product-card{ + position:relative; + transform-style:preserve-3d; + transition:transform .3s var(--ease), box-shadow .3s var(--ease); +} +.product-card .product-img{ transform:translateZ(20px); } +.product-card .product-info{ transform:translateZ(12px); } + +/* 卡片表面柔和高光反射(::after 跟随鼠标位置,浮于卡片最前层)*/ +.product-card::after{ + content:''; + position:absolute; + inset:0; + border-radius:inherit; + background:radial-gradient(circle at var(--mx,50%) var(--my,50%), rgba(255,255,255,0.40) 0%, transparent 50%); + opacity:0; + transition:opacity .4s var(--ease); + pointer-events:none; + z-index:2; + transform:translateZ(30px); +} +.product-card:hover::after{ opacity:1; } + +/* 页面入场动画(各区块淡入上滑,错开延迟)*/ +@keyframes fadeInUp{ from{ opacity:0; transform:translateY(30px); } to{ opacity:1; transform:translateY(0); } } +.top-strip{ animation:fadeInUp .8s var(--ease) both; animation-delay:0s; } +.navbar{ animation:fadeInUp .8s var(--ease) both; animation-delay:.10s; } +.hero{ animation:fadeInUp .8s var(--ease) both; animation-delay:.20s; } +.values{ animation:fadeInUp .8s var(--ease) both; animation-delay:.30s; } +.category-bar{ animation:fadeInUp .8s var(--ease) both; animation-delay:.40s; } +.shop{ animation:fadeInUp .8s var(--ease) both; animation-delay:.50s; } +.featured{ animation:fadeInUp .8s var(--ease) both; animation-delay:.60s; } +.footer{ animation:fadeInUp .8s var(--ease) both; animation-delay:.70s; } + +/* 移动端关闭光斑 / 尊重「减弱动效」偏好 */ +@media (max-width: 860px){ .cursor-glow{ display:none; } } +@media (prefers-reduced-motion: reduce){ + .cursor-glow{ display:none; } + .top-strip,.navbar,.hero,.values,.category-bar,.shop,.featured,.footer{ animation:none; } + .product-card{ transition:none; } + .product-card::after{ transition:none; } +} @@ -1473,6 +1538,50 @@ async function init() { updateCartUI(); } init(); + +// ========== 3D 动效 & 鼠标光影(北欧极简 · 克制优雅)========== +(function(){ + var reduceMotion = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches; + if (reduceMotion) return; + + /* —— 全局鼠标跟随柔光斑(轻柔拖尾,北欧式优雅)—— */ + var cursorGlow = document.createElement('div'); + cursorGlow.className = 'cursor-glow'; + document.body.appendChild(cursorGlow); + var gx = window.innerWidth / 2, gy = window.innerHeight / 2; + var tx = gx, ty = gy; + cursorGlow.style.transform = 'translate3d(' + gx + 'px,' + gy + 'px,0) translate(-50%,-50%)'; + document.addEventListener('mousemove', function(e){ tx = e.clientX; ty = e.clientY; }); + (function loop(){ + gx += (tx - gx) * 0.16; + gy += (ty - gy) * 0.16; + cursorGlow.style.transform = 'translate3d(' + gx.toFixed(2) + 'px,' + gy.toFixed(2) + 'px,0) translate(-50%,-50%)'; + requestAnimationFrame(loop); + })(); + + /* —— 产品卡片 3D 倾斜(最大 6°,柔和流畅;事件委托兼容动态渲染)—— */ + var activeCard = null; + document.addEventListener('mousemove', function(e){ + var card = (e.target && e.target.closest) ? e.target.closest('.product-card') : null; + if (card !== activeCard){ + if (activeCard){ activeCard.style.transform = ''; } + activeCard = card; + } + if (!card) return; + var rect = card.getBoundingClientRect(); + var cx = rect.left + rect.width / 2; + var cy = rect.top + rect.height / 2; + var rx = ((e.clientY - cy) / rect.height) * -6; // 北欧克制:最大 6° + var ry = ((e.clientX - cx) / rect.width) * 6; + card.style.transform = 'perspective(1000px) rotateX(' + rx.toFixed(2) + 'deg) rotateY(' + ry.toFixed(2) + 'deg) translateY(-6px)'; + card.style.setProperty('--mx', ((e.clientX - rect.left) / rect.width * 100).toFixed(1) + '%'); + card.style.setProperty('--my', ((e.clientY - rect.top) / rect.height * 100).toFixed(1) + '%'); + }); + /* 鼠标移出文档时复位倾斜 */ + document.addEventListener('mouseleave', function(){ + if (activeCard){ activeCard.style.transform = ''; activeCard = null; } + }); +})();