feat: 跨境电商首页高端重设计 - 全屏动态壁纸+光追效果
- 全屏Hero: 深色背景+Canvas粒子网络动态壁纸(80粒子红/金/橙) - 光追效果: 鼠标移动时粒子被吸引+射线连接+8道放射光追 - 悬浮导航栏: 半透明毛玻璃+滚动变色(深色→白色) - 渐变标题: 红金渐变文字+发光效果 - 统计数据条: 4项核心数据(18+品类/50万用户/99%好评/7天退换) - 滚动提示: 底部弹跳动画箭头
This commit is contained in:
262
web/dist/shop/index.html
vendored
262
web/dist/shop/index.html
vendored
@@ -37,7 +37,11 @@ img { max-width:100%; display:block; }
|
|||||||
.topbar a { color:var(--primary-light); }
|
.topbar a { color:var(--primary-light); }
|
||||||
|
|
||||||
/* ========== 导航栏 ========== */
|
/* ========== 导航栏 ========== */
|
||||||
.navbar { background:var(--surface); box-shadow:var(--shadow); position:sticky; top:0; z-index:100; }
|
.topbar { background:#0a0a0f; color:rgba(255,255,255,0.6); }
|
||||||
|
.navbar { background:rgba(10,10,15,0.6); backdrop-filter:blur(20px); position:fixed; top:32px; left:0; right:0; z-index:100; border-bottom:1px solid rgba(255,255,255,0.06); }
|
||||||
|
.navbar .nav-links a, .navbar .nav-brand, .navbar .search-box input, .navbar .search-box svg, .navbar .nav-actions span { color:rgba(255,255,255,0.85) !important; }
|
||||||
|
.navbar .search-box { background:rgba(255,255,255,0.06) !important; border:1px solid rgba(255,255,255,0.1) !important; }
|
||||||
|
.navbar .search-box input::placeholder { color:rgba(255,255,255,0.4) !important; }
|
||||||
.nav-container { max-width:1280px; margin:0 auto; padding:0 24px; display:flex; align-items:center; gap:32px; height:64px; }
|
.nav-container { max-width:1280px; margin:0 auto; padding:0 24px; display:flex; align-items:center; gap:32px; height:64px; }
|
||||||
.logo { font-size:24px; font-weight:800; color:var(--primary); display:flex; align-items:center; gap:8px; white-space:nowrap; }
|
.logo { font-size:24px; font-weight:800; color:var(--primary); display:flex; align-items:center; gap:8px; white-space:nowrap; }
|
||||||
.logo svg { width:28px; height:28px; }
|
.logo svg { width:28px; height:28px; }
|
||||||
@@ -54,16 +58,33 @@ img { max-width:100%; display:block; }
|
|||||||
.nav-actions svg { width:22px; height:22px; color:var(--text); }
|
.nav-actions svg { width:22px; height:22px; color:var(--text); }
|
||||||
.cart-badge { position:absolute; top:2px; right:2px; background:var(--primary); color:#fff; font-size:11px; font-weight:700; min-width:18px; height:18px; border-radius:9px; display:flex; align-items:center; justify-content:center; padding:0 4px; }
|
.cart-badge { position:absolute; top:2px; right:2px; background:var(--primary); color:#fff; font-size:11px; font-weight:700; min-width:18px; height:18px; border-radius:9px; display:flex; align-items:center; justify-content:center; padding:0 4px; }
|
||||||
|
|
||||||
/* ========== Hero 轮播 ========== */
|
/* ========== Hero 动态壁纸 ========== */
|
||||||
.hero { max-width:1280px; margin:24px auto; padding:0 24px; }
|
.hero { position:relative; width:100%; height:100vh; min-height:640px; overflow:hidden; background:#0a0a0f; }
|
||||||
.hero-banner { background:linear-gradient(135deg, #E63946 0%, #D62828 50%, #1D3557 100%); border-radius:var(--radius-lg); padding:60px 48px; color:#fff; position:relative; overflow:hidden; min-height:280px; display:flex; align-items:center; }
|
#heroCanvas { position:absolute; inset:0; width:100%; height:100%; z-index:1; }
|
||||||
.hero-banner::before { content:''; position:absolute; top:-50%; right:-10%; width:400px; height:400px; background:rgba(255,255,255,0.08); border-radius:50%; }
|
.hero-overlay { position:absolute; inset:0; z-index:2; background:radial-gradient(ellipse at 30% 40%, rgba(230,57,70,0.15) 0%, transparent 50%),linear-gradient(180deg,rgba(10,10,15,0.3) 0%,rgba(10,10,15,0.7) 70%,rgba(10,10,15,0.95) 100%); pointer-events:none; }
|
||||||
.hero-banner::after { content:''; position:absolute; bottom:-30%; right:20%; width:300px; height:300px; background:rgba(255,255,255,0.05); border-radius:50%; }
|
.hero-light { position:absolute; z-index:3; pointer-events:none; width:600px; height:600px; border-radius:50%; background:radial-gradient(circle,rgba(230,57,70,0.25) 0%,rgba(230,57,70,0.08) 30%,transparent 60%); transform:translate(-50%,-50%); mix-blend-mode:screen; filter:blur(20px); transition:opacity .3s; opacity:0; }
|
||||||
.hero-content { position:relative; z-index:1; max-width:560px; }
|
.hero-light.active { opacity:1; }
|
||||||
.hero-content h1 { font-size:42px; font-weight:800; line-height:1.2; margin-bottom:16px; }
|
.hero-content { position:absolute; inset:0; z-index:4; display:flex; flex-direction:column; justify-content:center; align-items:flex-start; padding:0 8vw; max-width:1400px; margin:0 auto; }
|
||||||
.hero-content p { font-size:18px; opacity:0.9; margin-bottom:28px; }
|
.hero-badge { display:inline-flex; align-items:center; gap:8px; padding:6px 18px; border-radius:100px; background:rgba(255,255,255,0.06); border:1px solid rgba(255,255,255,0.12); font-size:13px; color:rgba(255,255,255,0.8); margin-bottom:24px; backdrop-filter:blur(10px); }
|
||||||
.hero-btn { display:inline-flex; align-items:center; gap:8px; background:#fff; color:var(--primary); padding:14px 32px; border-radius:var(--radius); font-size:16px; font-weight:700; transition:var(--transition); }
|
.hero-badge .dot { width:6px; height:6px; border-radius:50%; background:#E63946; box-shadow:0 0 8px #E63946; animation:pulse 2s infinite; }
|
||||||
.hero-btn:hover { transform:translateY(-2px); box-shadow:0 8px 24px rgba(0,0,0,0.2); }
|
@keyframes pulse { 0%,100%{opacity:1} 50%{opacity:0.3} }
|
||||||
|
.hero-content h1 { font-size:72px; font-weight:900; line-height:1.05; letter-spacing:-2px; color:#fff; margin-bottom:20px; text-shadow:0 4px 30px rgba(0,0,0,0.5); }
|
||||||
|
.hero-content h1 .accent { background:linear-gradient(135deg,#E63946 0%,#FF6B6B 50%,#FFD700 100%); -webkit-background-clip:text; -webkit-text-fill-color:transparent; background-clip:text; }
|
||||||
|
.hero-content p { font-size:20px; color:rgba(255,255,255,0.6); max-width:560px; line-height:1.6; margin-bottom:36px; }
|
||||||
|
.hero-actions { display:flex; gap:16px; align-items:center; }
|
||||||
|
.hero-btn-primary { display:inline-flex; align-items:center; gap:10px; background:linear-gradient(135deg,#E63946,#D62828); color:#fff; padding:16px 40px; border-radius:100px; font-size:16px; font-weight:700; transition:all .3s; box-shadow:0 8px 32px rgba(230,57,70,0.4); border:none; cursor:pointer; }
|
||||||
|
.hero-btn-primary:hover { transform:translateY(-3px); box-shadow:0 12px 40px rgba(230,57,70,0.55); }
|
||||||
|
.hero-btn-ghost { display:inline-flex; align-items:center; gap:8px; background:rgba(255,255,255,0.06); color:#fff; padding:16px 32px; border-radius:100px; font-size:15px; font-weight:600; border:1px solid rgba(255,255,255,0.15); cursor:pointer; transition:all .3s; backdrop-filter:blur(10px); }
|
||||||
|
.hero-btn-ghost:hover { background:rgba(255,255,255,0.12); border-color:rgba(255,255,255,0.25); }
|
||||||
|
.hero-stats { position:absolute; bottom:48px; left:0; right:0; z-index:4; display:flex; gap:48px; justify-content:center; padding:0 24px; }
|
||||||
|
.hero-stat { text-align:center; }
|
||||||
|
.hero-stat .num { font-size:36px; font-weight:800; color:#fff; }
|
||||||
|
.hero-stat .num span { color:#E63946; }
|
||||||
|
.hero-stat .label { font-size:13px; color:rgba(255,255,255,0.5); margin-top:2px; }
|
||||||
|
.hero-scroll { position:absolute; bottom:20px; left:50%; transform:translateX(-50%); z-index:4; color:rgba(255,255,255,0.4); font-size:12px; display:flex; flex-direction:column; align-items:center; gap:6px; animation:bounce 2s infinite; }
|
||||||
|
@keyframes bounce { 0%,100%{transform:translateX(-50%) translateY(0)} 50%{transform:translateX(-50%) translateY(-8px)} }
|
||||||
|
.hero-scroll svg { width:20px; height:20px; }
|
||||||
|
@media(max-width:768px){ .hero-content h1{font-size:42px} .hero-content p{font-size:16px} .hero-stats{gap:20px} .hero-stat .num{font-size:24px} }
|
||||||
|
|
||||||
/* ========== 优势条 ========== */
|
/* ========== 优势条 ========== */
|
||||||
.features-strip { max-width:1280px; margin:24px auto; padding:0 24px; display:grid; grid-template-columns:repeat(4,1fr); gap:16px; }
|
.features-strip { max-width:1280px; margin:24px auto; padding:0 24px; display:grid; grid-template-columns:repeat(4,1fr); gap:16px; }
|
||||||
@@ -288,18 +309,33 @@ img { max-width:100%; display:block; }
|
|||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<!-- Hero Banner -->
|
<!-- Hero 动态壁纸 -->
|
||||||
<div class="hero">
|
<div class="hero">
|
||||||
<div class="hero-banner">
|
<canvas id="heroCanvas"></canvas>
|
||||||
|
<div class="hero-overlay"></div>
|
||||||
|
<div class="hero-light" id="heroLight"></div>
|
||||||
<div class="hero-content">
|
<div class="hero-content">
|
||||||
<h1>全球好物<br>跨境直达</h1>
|
<div class="hero-badge"><span class="dot"></span> 全球直邮 · 2026 新季上线</div>
|
||||||
<p>精选 18+ 品类好物,覆盖智能电子、家居生活、时尚运动,全球直邮,品质保障</p>
|
<h1>全球好物<br><span class="accent">跨境直达</span></h1>
|
||||||
<a href="#" class="hero-btn" onclick="scrollToProducts();return false;">
|
<p>精选 18+ 品类好物,覆盖智能电子、家居生活、时尚运动,全球直邮,品质保障。沉浸式购物体验,由此开启。</p>
|
||||||
|
<div class="hero-actions">
|
||||||
|
<button class="hero-btn-primary" onclick="scrollToProducts()">
|
||||||
立即选购
|
立即选购
|
||||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="width:20px;height:20px"><path d="M5 12h14M12 5l7 7-7 7"/></svg>
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="width:20px;height:20px"><path d="M5 12h14M12 5l7 7-7 7"/></svg>
|
||||||
</a>
|
</button>
|
||||||
|
<button class="hero-btn-ghost" onclick="loadFeatured()">探索精选</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="hero-stats">
|
||||||
|
<div class="hero-stat"><div class="num">18<span>+</span></div><div class="label">品类好物</div></div>
|
||||||
|
<div class="hero-stat"><div class="num">50<span>万</span></div><div class="label">全球用户</div></div>
|
||||||
|
<div class="hero-stat"><div class="num">99<span>%</span></div><div class="label">好评率</div></div>
|
||||||
|
<div class="hero-stat"><div class="num">7<span>天</span></div><div class="label">无理由退换</div></div>
|
||||||
|
</div>
|
||||||
|
<div class="hero-scroll">
|
||||||
|
<span>向下滚动</span>
|
||||||
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 5v14M5 12l7 7 7-7"/></svg>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 优势条 -->
|
<!-- 优势条 -->
|
||||||
@@ -827,6 +863,198 @@ async function init() {
|
|||||||
|
|
||||||
init();
|
init();
|
||||||
|
|
||||||
|
// ========== Hero 动态壁纸 + 光追效果 ==========
|
||||||
|
// 导航栏滚动变色
|
||||||
|
window.addEventListener('scroll', function() {
|
||||||
|
var navbar = document.querySelector('.navbar');
|
||||||
|
var topbar = document.querySelector('.topbar');
|
||||||
|
if (window.scrollY > 80) {
|
||||||
|
navbar.style.background = 'rgba(255,255,255,0.95)';
|
||||||
|
navbar.style.backdropFilter = 'blur(20px)';
|
||||||
|
navbar.style.boxShadow = '0 2px 12px rgba(0,0,0,0.06)';
|
||||||
|
navbar.style.borderBottomColor = 'rgba(0,0,0,0.06)';
|
||||||
|
var links = navbar.querySelectorAll('.nav-links a, .nav-brand, .search-box input, .search-box svg, .nav-actions span');
|
||||||
|
links.forEach(function(el){ el.style.color = ''; });
|
||||||
|
var search = navbar.querySelector('.search-box');
|
||||||
|
if (search) { search.style.background = 'var(--bg)'; search.style.border = '1px solid var(--border)'; }
|
||||||
|
} else {
|
||||||
|
navbar.style.background = 'rgba(10,10,15,0.6)';
|
||||||
|
navbar.style.boxShadow = 'none';
|
||||||
|
navbar.style.borderBottomColor = 'rgba(255,255,255,0.06)';
|
||||||
|
}
|
||||||
|
if (topbar) topbar.style.opacity = window.scrollY > 32 ? '0' : '1';
|
||||||
|
});
|
||||||
|
|
||||||
|
(function(){
|
||||||
|
var canvas = document.getElementById('heroCanvas');
|
||||||
|
if (!canvas) return;
|
||||||
|
var ctx = canvas.getContext('2d');
|
||||||
|
var heroLight = document.getElementById('heroLight');
|
||||||
|
var W = 0, H = 0, dpr = window.devicePixelRatio || 1;
|
||||||
|
|
||||||
|
function resize() {
|
||||||
|
var rect = canvas.getBoundingClientRect();
|
||||||
|
W = rect.width; H = rect.height;
|
||||||
|
canvas.width = W * dpr; canvas.height = H * dpr;
|
||||||
|
ctx.scale(dpr, dpr);
|
||||||
|
}
|
||||||
|
resize();
|
||||||
|
window.addEventListener('resize', resize);
|
||||||
|
|
||||||
|
// 粒子系统 — 流动的光丝
|
||||||
|
var particles = [];
|
||||||
|
var PARTICLE_COUNT = 80;
|
||||||
|
for (var i = 0; i < PARTICLE_COUNT; i++) {
|
||||||
|
particles.push({
|
||||||
|
x: Math.random() * W,
|
||||||
|
y: Math.random() * H,
|
||||||
|
vx: (Math.random() - 0.5) * 0.3,
|
||||||
|
vy: (Math.random() - 0.5) * 0.3,
|
||||||
|
size: Math.random() * 3 + 1,
|
||||||
|
hue: Math.random() < 0.6 ? 355 : (Math.random() < 0.5 ? 45 : 15), // 红/金/橙
|
||||||
|
alpha: Math.random() * 0.5 + 0.4,
|
||||||
|
life: Math.random()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 鼠标位置
|
||||||
|
var mx = W / 2, my = H / 2;
|
||||||
|
var hasMouse = false;
|
||||||
|
|
||||||
|
canvas.parentElement.addEventListener('mousemove', function(e) {
|
||||||
|
var rect = canvas.getBoundingClientRect();
|
||||||
|
mx = e.clientX - rect.left;
|
||||||
|
my = e.clientY - rect.top;
|
||||||
|
if (!hasMouse) { hasMouse = true; heroLight.classList.add('active'); }
|
||||||
|
heroLight.style.left = mx + 'px';
|
||||||
|
heroLight.style.top = my + 'px';
|
||||||
|
});
|
||||||
|
canvas.parentElement.addEventListener('mouseleave', function() {
|
||||||
|
hasMouse = false;
|
||||||
|
heroLight.classList.remove('active');
|
||||||
|
});
|
||||||
|
|
||||||
|
// 动态壁纸主循环
|
||||||
|
function animate() {
|
||||||
|
// 深色背景渐变
|
||||||
|
var grad = ctx.createRadialGradient(W * 0.3, H * 0.4, 0, W * 0.3, H * 0.4, W * 0.8);
|
||||||
|
grad.addColorStop(0, 'rgba(30,15,20,0.15)');
|
||||||
|
grad.addColorStop(1, 'rgba(10,10,15,0.2)');
|
||||||
|
ctx.fillStyle = 'rgba(10,10,15,0.15)';
|
||||||
|
ctx.fillRect(0, 0, W, H);
|
||||||
|
ctx.fillStyle = grad;
|
||||||
|
ctx.fillRect(0, 0, W, H);
|
||||||
|
|
||||||
|
// 绘制流动的曲线网络
|
||||||
|
for (var i = 0; i < particles.length; i++) {
|
||||||
|
var p = particles[i];
|
||||||
|
|
||||||
|
// 鼠标吸引/排斥
|
||||||
|
if (hasMouse) {
|
||||||
|
var dx = mx - p.x;
|
||||||
|
var dy = my - p.y;
|
||||||
|
var dist = Math.sqrt(dx * dx + dy * dy);
|
||||||
|
if (dist < 200) {
|
||||||
|
var force = (1 - dist / 200) * 0.02;
|
||||||
|
p.vx += dx / dist * force;
|
||||||
|
p.vy += dy / dist * force;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新位置
|
||||||
|
p.x += p.vx;
|
||||||
|
p.y += p.vy;
|
||||||
|
p.vx *= 0.98;
|
||||||
|
p.vy *= 0.98;
|
||||||
|
p.life += 0.005;
|
||||||
|
|
||||||
|
// 边界回弹
|
||||||
|
if (p.x < 0) p.x = W;
|
||||||
|
if (p.x > W) p.x = 0;
|
||||||
|
if (p.y < 0) p.y = H;
|
||||||
|
if (p.y > H) p.y = 0;
|
||||||
|
|
||||||
|
// 绘制粒子
|
||||||
|
var pulse = Math.sin(p.life * Math.PI * 2) * 0.3 + 0.7;
|
||||||
|
var r = p.size * pulse;
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(p.x, p.y, r, 0, Math.PI * 2);
|
||||||
|
ctx.fillStyle = 'hsla(' + p.hue + ',80%,60%,' + (p.alpha * pulse) + ')';
|
||||||
|
ctx.fill();
|
||||||
|
|
||||||
|
// 光晕
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(p.x, p.y, r * 3, 0, Math.PI * 2);
|
||||||
|
var glow = ctx.createRadialGradient(p.x, p.y, 0, p.x, p.y, r * 3);
|
||||||
|
glow.addColorStop(0, 'hsla(' + p.hue + ',80%,60%,' + (p.alpha * 0.3) + ')');
|
||||||
|
glow.addColorStop(1, 'transparent');
|
||||||
|
ctx.fillStyle = glow;
|
||||||
|
ctx.fill();
|
||||||
|
|
||||||
|
// 连线 — 近距离粒子之间
|
||||||
|
for (var j = i + 1; j < particles.length; j++) {
|
||||||
|
var p2 = particles[j];
|
||||||
|
var ldx = p.x - p2.x;
|
||||||
|
var ldy = p.y - p2.y;
|
||||||
|
var ld = Math.sqrt(ldx * ldx + ldy * ldy);
|
||||||
|
if (ld < 150) {
|
||||||
|
var la = (1 - ld / 150) * 0.25;
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(p.x, p.y);
|
||||||
|
ctx.lineTo(p2.x, p2.y);
|
||||||
|
ctx.strokeStyle = 'hsla(' + p.hue + ',70%,55%,' + la + ')';
|
||||||
|
ctx.lineWidth = 0.5;
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 鼠标光追连线 — 鼠标附近的粒子向鼠标发射光线
|
||||||
|
if (hasMouse) {
|
||||||
|
var mdx = p.x - mx;
|
||||||
|
var mdy = p.y - my;
|
||||||
|
var md = Math.sqrt(mdx * mdx + mdy * mdy);
|
||||||
|
if (md < 250) {
|
||||||
|
var ma = (1 - md / 250) * 0.4;
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(p.x, p.y);
|
||||||
|
ctx.lineTo(mx, my);
|
||||||
|
ctx.strokeStyle = 'rgba(230,57,70,' + ma + ')';
|
||||||
|
ctx.lineWidth = 1;
|
||||||
|
ctx.stroke();
|
||||||
|
|
||||||
|
// 光追射线效果 — 在鼠标周围有明亮光点
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(mx, my, 2, 0, Math.PI * 2);
|
||||||
|
ctx.fillStyle = 'rgba(255,255,255,0.8)';
|
||||||
|
ctx.fill();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 鼠标处的光追放射线
|
||||||
|
if (hasMouse) {
|
||||||
|
for (var k = 0; k < 8; k++) {
|
||||||
|
var angle = (k / 8) * Math.PI * 2 + Date.now() * 0.0003;
|
||||||
|
var len = 80 + Math.sin(Date.now() * 0.002 + k) * 20;
|
||||||
|
var ex = mx + Math.cos(angle) * len;
|
||||||
|
var ey = my + Math.sin(angle) * len;
|
||||||
|
var rayGrad = ctx.createLinearGradient(mx, my, ex, ey);
|
||||||
|
rayGrad.addColorStop(0, 'rgba(230,57,70,0.15)');
|
||||||
|
rayGrad.addColorStop(1, 'transparent');
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(mx, my);
|
||||||
|
ctx.lineTo(ex, ey);
|
||||||
|
ctx.strokeStyle = rayGrad;
|
||||||
|
ctx.lineWidth = 2;
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
requestAnimationFrame(animate);
|
||||||
|
}
|
||||||
|
animate();
|
||||||
|
})();
|
||||||
|
|
||||||
// ========== 3D 动态效果 & 鼠标光影(新增)==========
|
// ========== 3D 动态效果 & 鼠标光影(新增)==========
|
||||||
(function(){
|
(function(){
|
||||||
var isTouch = window.matchMedia('(hover: none)').matches;
|
var isTouch = window.matchMedia('(hover: none)').matches;
|
||||||
|
|||||||
Reference in New Issue
Block a user