feat: 跨境电商3套模板添加3D动态光影效果
- shop: 红色经典风格 - 鼠标红色光斑+卡片8度3D倾斜+玻璃高光+Hero视差 - shop2: 暗黑霓虹风格 - 霓虹紫青光斑+卡片10度3D倾斜+霓虹高光+12个浮动粒子 - shop3: 北欧极简风格 - 柔和暖色光斑+卡片6度3D倾斜+柔和高光+入场动画
This commit is contained in:
90
web/dist/shop/index.html
vendored
90
web/dist/shop/index.html
vendored
@@ -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}}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user