144 lines
4.2 KiB
JavaScript
144 lines
4.2 KiB
JavaScript
export function initMorphEyes() {
|
|
const svg = document.querySelector(".identity svg");
|
|
if (!svg) return;
|
|
|
|
gsap.registerPlugin(MorphSVGPlugin);
|
|
|
|
const DURATION = 0.7;
|
|
const EASE_IN = "elastic.out(1.3, 0.35)";
|
|
const EASE_OUT = "elastic.out(1.3, 0.35)";
|
|
|
|
// lc-eye-l : composé de plusieurs éléments superposés
|
|
const lcEyeLIris = svg.querySelector("#lc-eye-l-iris");
|
|
const lcEyeLBase = svg.querySelector("#lc-eye-l-base");
|
|
const lcEyeLOverlays = svg.querySelectorAll(
|
|
"#lc-eye-l-sclera, #lc-eye-l-shadow, #lc-eye-l-sparkle"
|
|
);
|
|
|
|
// Les trois autres yeux : un seul compound path chacun
|
|
const lcEyeRIris = svg.querySelector("#lc-eye-r-iris");
|
|
const rcEyeLIris = svg.querySelector("#rc-eye-l-iris");
|
|
const rcEyeRIris = svg.querySelector("#rc-eye-r-iris");
|
|
|
|
// Groupes d'yeux pour le blink
|
|
const eyeGroupLcL = svg.querySelector("#lc-eye-l");
|
|
const eyeGroupLcR = svg.querySelector("#lc-eye-r");
|
|
const eyeGroupRcL = svg.querySelector("#rc-eye-l");
|
|
const eyeGroupRcR = svg.querySelector("#rc-eye-r");
|
|
const eyeGroups = [eyeGroupLcL, eyeGroupLcR, eyeGroupRcL, eyeGroupRcR];
|
|
|
|
// Paupières, sourcils, nez : révélés en fondu lors du passage en no-outfit
|
|
const faceOverlays = svg.querySelector("#face-overlays");
|
|
|
|
if (!lcEyeLIris || !lcEyeRIris || !rcEyeLIris || !rcEyeRIris) return;
|
|
|
|
const origins = {
|
|
lcEyeLIris: lcEyeLIris.getAttribute("d"),
|
|
lcEyeLBase: lcEyeLBase.getAttribute("d"),
|
|
lcEyeRIris: lcEyeRIris.getAttribute("d"),
|
|
rcEyeLIris: rcEyeLIris.getAttribute("d"),
|
|
rcEyeRIris: rcEyeRIris.getAttribute("d"),
|
|
};
|
|
|
|
let blinkTl = null;
|
|
|
|
function blink() {
|
|
blinkTl = gsap.timeline({ delay: DURATION + 0.1 });
|
|
blinkTl
|
|
.to(eyeGroups, { scaleY: 0, duration: 0.07, ease: "power2.in", transformOrigin: "center center" })
|
|
.to(eyeGroups, { scaleY: 1, duration: 0.1, ease: "power2.out" })
|
|
.to(eyeGroups, { scaleY: 0, duration: 0.07, ease: "power2.in", delay: 0.06 })
|
|
.to(eyeGroups, { scaleY: 1, duration: 0.1, ease: "power2.out" })
|
|
.to(eyeGroups, { scaleY: 0, duration: 0.07, ease: "power2.in", delay: 0.1 })
|
|
.to(eyeGroups, { scaleY: 1, duration: 0.12, ease: "power2.out" });
|
|
}
|
|
|
|
function morphToNoOutfit() {
|
|
if (blinkTl) blinkTl.kill();
|
|
gsap.set(eyeGroups, { scaleY: 1 });
|
|
|
|
gsap.to(lcEyeLIris, {
|
|
morphSVG: "#lc-eye-l-target",
|
|
duration: DURATION,
|
|
ease: EASE_IN,
|
|
});
|
|
// base + overlays disparaissent vite pour ne pas masquer le morph de l'iris
|
|
gsap.to([lcEyeLBase, ...lcEyeLOverlays], {
|
|
opacity: 0,
|
|
duration: 0.08,
|
|
ease: "power1.in",
|
|
});
|
|
|
|
gsap.to(lcEyeRIris, {
|
|
morphSVG: "#lc-eye-r-target",
|
|
duration: DURATION,
|
|
delay: 0.04,
|
|
ease: EASE_IN,
|
|
});
|
|
gsap.to(rcEyeLIris, {
|
|
morphSVG: "#rc-eye-l-target",
|
|
duration: DURATION,
|
|
delay: 0.02,
|
|
ease: EASE_IN,
|
|
});
|
|
gsap.to(rcEyeRIris, {
|
|
morphSVG: "#rc-eye-r-target",
|
|
duration: DURATION,
|
|
delay: 0.06,
|
|
ease: EASE_IN,
|
|
});
|
|
|
|
gsap.to(faceOverlays, {
|
|
opacity: 1,
|
|
duration: DURATION * 0.8,
|
|
delay: DURATION * 0.25,
|
|
ease: "power1.out",
|
|
});
|
|
}
|
|
|
|
function morphToKawai() {
|
|
gsap.to(lcEyeLIris, {
|
|
morphSVG: origins.lcEyeLIris,
|
|
duration: DURATION,
|
|
ease: EASE_OUT,
|
|
});
|
|
// base + overlays réapparaissent seulement après que l'iris ait fini de morphier
|
|
gsap.to([lcEyeLBase, ...lcEyeLOverlays], {
|
|
opacity: 1,
|
|
duration: 0.1,
|
|
delay: DURATION,
|
|
ease: "power1.out",
|
|
});
|
|
|
|
gsap.to(lcEyeRIris, {
|
|
morphSVG: origins.lcEyeRIris,
|
|
duration: DURATION,
|
|
delay: 0.04,
|
|
ease: EASE_OUT,
|
|
});
|
|
gsap.to(rcEyeLIris, {
|
|
morphSVG: origins.rcEyeLIris,
|
|
duration: DURATION,
|
|
delay: 0.02,
|
|
ease: EASE_OUT,
|
|
});
|
|
gsap.to(rcEyeRIris, {
|
|
morphSVG: origins.rcEyeRIris,
|
|
duration: DURATION,
|
|
delay: 0.06,
|
|
ease: EASE_OUT,
|
|
});
|
|
|
|
gsap.to(faceOverlays, {
|
|
opacity: 0,
|
|
duration: DURATION * 0.35,
|
|
ease: "power2.in",
|
|
});
|
|
|
|
blink();
|
|
}
|
|
|
|
const identity = document.querySelector(".identity");
|
|
identity.addEventListener("mouseenter", morphToNoOutfit);
|
|
identity.addEventListener("mouseleave", morphToKawai);
|
|
}
|