Skiply.ai/main/shoe-animation-vanilla.js
2026-08-19 13:41:35 +05:30

75 lines
2.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* ================================================
Shoe Showcase Interactive Mouse-Driven Animation
================================================
- Background panels expand/contract based on mouse X
- Phone mockups fade in/out (only phones, text stays)
- On mouse leave → smoothly resets to 50/50
================================================ */
document.addEventListener('DOMContentLoaded', () => {
const showcase = document.getElementById('showcase');
const bgRed = document.getElementById('bg-red');
const bgBlack = document.getElementById('bg-black');
const phoneRed = document.getElementById('phone-red');
const phoneBlack = document.getElementById('phone-black');
let targetRatio = 0.5;
let currentRatio = 0.5;
const LERP_SPEED = 0.1;
function lerp(a, b, t) {
return a + (b - a) * t;
}
function clamp(v, lo, hi) {
return Math.min(hi, Math.max(lo, v));
}
/* ---- mouse tracking ---- */
showcase.addEventListener('mousemove', (e) => {
const rect = showcase.getBoundingClientRect();
targetRatio = clamp((e.clientX - rect.left) / rect.width, 0, 1);
});
showcase.addEventListener('mouseleave', () => {
targetRatio = 0.5;
});
/* ---- animation loop ---- */
function animate() {
currentRatio = lerp(currentRatio, targetRatio, LERP_SPEED);
const r = currentRatio;
/* 1. Background panel flex (full-width decorative) */
const redFlex = lerp(3.5, 0.3, r);
const blackFlex = lerp(0.3, 3.5, r);
bgRed.style.flex = redFlex;
bgBlack.style.flex = blackFlex;
/* 2. Phone mockup scale / opacity / translate */
const bias = (0.5 - r) * 2; // +1 red, -1 black
const redScale = 1 + clamp(bias, 0, 1) * 0.3;
const redOpacity = clamp(1 + bias * 3, 0, 1);
const redShiftX = clamp(bias, 0, 1) * 60;
const blackScale = 1 + clamp(-bias, 0, 1) * 0.3;
const blackOpacity = clamp(1 - bias * 3, 0, 1);
const blackShiftX = clamp(-bias, 0, 1) * -60;
phoneRed.style.transform = `scale(${redScale}) translateX(${redShiftX}px)`;
phoneRed.style.opacity = redOpacity;
phoneBlack.style.transform = `scale(${blackScale}) translateX(${blackShiftX}px)`;
phoneBlack.style.opacity = blackOpacity;
/* 3. Text always stays visible — no opacity changes */
requestAnimationFrame(animate);
}
animate();
});