diff --git a/assets/js/characters.js b/assets/js/characters.js
deleted file mode 100644
index 4f6577a..0000000
--- a/assets/js/characters.js
+++ /dev/null
@@ -1,217 +0,0 @@
-document.addEventListener("DOMContentLoaded", () => {
- const svg = document.querySelector(".characters svg");
- initCharacterJump();
- initPupilTracking(svg);
-});
-
-function initCharacterJump() {
- // Gravité constante — contrairement à un ressort, la force est uniforme :
- // la chute accélère jusqu'au sol au lieu de ralentir en apesanteur
- const GRAVITY = 900; // accélération vers le bas (unités SVG/s²)
- const LAUNCH_V = 225; // impulsion vers le haut (unités SVG/s)
- const RESTITUTION = 0.15; // restitution du mini-rebond à l'atterrissage
- const CYCLE = 1200; // ms entre deux lancers
- const SQUAT_MS = 220; // durée du squat avant lancer
- const EXTEND_MS = 100; // extension des jambes juste après le lancer
- const FOOT_ROT = 35; // rotation max des pieds (degrés)
- // Distance dont le top des jambes descend à compression max (173.32 → 197)
- const BODY_SQUAT = 197 - 173.32;
-
- const rightChar = document.getElementById("right-character");
- const rightBody = document.getElementById("right-character-body");
- const rightLeg = document.getElementById("right-leg1");
- const leftLeg = document.getElementById("left-leg1");
- const rightFoot = document.getElementById("right-foot1");
- const leftFoot = document.getElementById("left-foot1");
-
- const LEG_R_REST = "M209.01,216.53C221.33,194.34 209.01,173.32 209.01,173.32";
- const LEG_L_REST = "M189.01,216.53C176.69,194.34 189.01,173.32 189.01,173.32";
- const LEG_R_COMP = "M209.01,216.53C231.01,207 209.01,197 209.01,197";
- const LEG_L_COMP = "M189.01,216.53C167.01,207 189.01,197 189.01,197";
-
- function lerpPath(p1, p2, t) {
- const re = /-?\d+\.?\d*/g;
- const n1 = p1.match(re).map(Number);
- const n2 = p2.match(re).map(Number);
- let i = 0;
- return p1.replace(re, () => {
- const v = n1[i] + (n2[i] - n1[i]) * t;
- i++;
- return v.toFixed(2);
- });
- }
-
- const easeInOut = t => t < 0.5 ? 2*t*t : 1 - (-2*t+2)**2/2;
- const easeIn = t => t*t;
-
- // Crée un ressort secondaire indépendant (fermeture sur pos/vel)
- function makeSpring(k, c) {
- let pos = 0, vel = 0;
- return (target, dt) => {
- const acc = -k * (pos - target) - c * vel;
- vel += acc * dt;
- pos += vel * dt;
- return pos;
- };
- }
-
- // Cinématique verticale — pos > 0 = en l'air
- let yPos = 0, yVel = 0, landingCompress = 0;
-
- // Ressorts secondaires : chaque partie suit sa cible avec son propre délai
- // Corps/tête : k élevé → réactif, léger overshoot sur le relâché
- // Jambes : mêmes paramètres que le corps pour rester visuellement connectés
- // Pieds : k bas → floppy, ils traînent naturellement
- const bodySpring = makeSpring(300, 18);
- const legSpring = makeSpring(300, 18);
- const rFootSpring = makeSpring(150, 10);
- const lFootSpring = makeSpring(150, 10);
-
- let hovered = false;
- let inCycle = false;
- let cycleStart = null;
- let launched = false;
- let lastTime = null;
-
- const wrapper = document.querySelector(".characters");
- wrapper.addEventListener("mouseenter", () => { hovered = true; });
- wrapper.addEventListener("mouseleave", () => { hovered = false; });
-
- function tick(time) {
- if (!lastTime) lastTime = time;
- const dt = Math.min((time - lastTime) / 1000, 0.05);
- lastTime = time;
-
- if (hovered && !inCycle) {
- cycleStart = time;
- inCycle = true;
- launched = false;
- }
-
- let elapsed = inCycle ? time - cycleStart : 0;
- if (inCycle && elapsed >= CYCLE) {
- if (hovered) {
- cycleStart = time;
- elapsed = 0;
- launched = false;
- } else {
- inCycle = false;
- elapsed = 0;
- }
- }
-
- // Squat + lancer seulement pendant un cycle actif
- let squatCompress = 0;
- if (inCycle) {
- if (elapsed < SQUAT_MS) {
- squatCompress = easeInOut(elapsed / SQUAT_MS);
- } else if (elapsed < SQUAT_MS + EXTEND_MS) {
- squatCompress = 1 - easeIn((elapsed - SQUAT_MS) / EXTEND_MS);
- }
-
- if (!launched && elapsed >= SQUAT_MS) {
- yVel += LAUNCH_V;
- launched = true;
- }
- }
-
- // Cinématique verticale : gravité constante, contrainte sol
- if (yPos > 0 || yVel > 0) {
- yVel -= GRAVITY * dt;
- }
- yPos += yVel * dt;
-
- if (yPos < 0) {
- if (yVel < 0) {
- const impactV = -yVel;
- if (impactV > 50) {
- landingCompress = Math.min(0.6, impactV / LAUNCH_V * 0.8);
- }
- yVel = impactV > 15 ? impactV * RESTITUTION : 0;
- }
- yPos = 0;
- }
- landingCompress = Math.max(0, landingCompress - 4 * dt);
-
- const ty = -yPos;
-
- const compressTarget = Math.max(squatCompress, landingCompress);
-
- // Rotation cible des pieds proportionnelle à la hauteur
- const footRotTarget = yPos > 3
- ? Math.min(1, (yPos - 3) / 12)
- : 0;
-
- // Ressorts secondaires : calcul des valeurs avec inertie propre
- const bodyDisp = bodySpring(compressTarget * BODY_SQUAT, dt);
- const legMorph = Math.max(0, Math.min(1, legSpring(compressTarget, dt)));
- const rFootAngle = rFootSpring(footRotTarget * FOOT_ROT, dt);
- const lFootAngle = lFootSpring(-footRotTarget * FOOT_ROT, dt);
-
- rightChar.setAttribute("transform", `translate(0,${ty.toFixed(2)})`);
- rightBody.setAttribute("transform", `translate(0,${bodyDisp.toFixed(2)})`);
- rightLeg.setAttribute("d", lerpPath(LEG_R_REST, LEG_R_COMP, legMorph));
- leftLeg.setAttribute("d", lerpPath(LEG_L_REST, LEG_L_COMP, legMorph));
- rightFoot.setAttribute("transform", `rotate(${rFootAngle.toFixed(1)},209.01,217.6)`);
- leftFoot.setAttribute("transform", `rotate(${lFootAngle.toFixed(1)},189.01,217.6)`);
-
- requestAnimationFrame(tick);
- }
-
- requestAnimationFrame(tick);
-}
-
-function initPupilTracking(svg) {
- const VB_W = 304;
- const VB_H = 259;
- const S = 1.267471;
- const BASE_TX = S * 52.5;
- const BASE_TY = S * 87.5;
- const MAX_R = 3.5;
- const LERP = 0.12;
-
- // Centre de chaque œil — personnage gauche uniquement
- const eyes = [
- { id: "left-pupil", cx: 54.03, cy: 86.79 },
- { id: "right-pupil", cx: 103.55, cy: 86.79 },
- ];
-
- const cur = eyes.map(e => ({ x: e.cx, y: e.cy }));
- const tgt = eyes.map(e => ({ x: e.cx, y: e.cy }));
-
- document.addEventListener("mousemove", (e) => {
- const rect = svg.getBoundingClientRect();
- const mx = (e.clientX - rect.left) * (VB_W / rect.width);
- const my = (e.clientY - rect.top) * (VB_H / rect.height);
-
- eyes.forEach((eye, i) => {
- const dx = mx - eye.cx;
- const dy = my - eye.cy;
- const dist = Math.hypot(dx, dy);
- const ratio = dist > 0 ? Math.min(MAX_R, dist) / dist : 0;
- tgt[i].x = eye.cx + dx * ratio;
- tgt[i].y = eye.cy + dy * ratio;
- });
- });
-
- document.addEventListener("mouseleave", () => {
- eyes.forEach((eye, i) => {
- tgt[i].x = eye.cx;
- tgt[i].y = eye.cy;
- });
- });
-
- function tick() {
- eyes.forEach((eye, i) => {
- cur[i].x += (tgt[i].x - cur[i].x) * LERP;
- cur[i].y += (tgt[i].y - cur[i].y) * LERP;
- document.getElementById(eye.id)?.setAttribute(
- "transform",
- `matrix(${S},0,0,${S},${cur[i].x - BASE_TX},${cur[i].y - BASE_TY})`
- );
- });
- requestAnimationFrame(tick);
- }
-
- requestAnimationFrame(tick);
-}
diff --git a/assets/js/characters/jump.js b/assets/js/characters/jump.js
new file mode 100644
index 0000000..095a480
--- /dev/null
+++ b/assets/js/characters/jump.js
@@ -0,0 +1,192 @@
+const RIGHT_LEG_AXIS_X = 209.01;
+const LEFT_LEG_AXIS_X = 189.01;
+const ANKLE_Y = 216.53;
+const HIP_Y_STANDING = 173.32;
+const HIP_Y_SQUATTING = 197;
+
+// Point de contrôle de Bézier qui détermine la courbure latérale de la jambe
+const rightLegBowControlStanding = { x: 221.33, y: 194.34 };
+const rightLegBowControlSquatting = { x: 231.01, y: 207 };
+const leftLegBowControlStanding = { x: 176.69, y: 194.34 };
+const leftLegBowControlSquatting = { x: 167.01, y: 207 };
+
+function buildLegSvgPath(legAxisX, bowControl, hipY) {
+ return `M${legAxisX},${ANKLE_Y}C${bowControl.x},${bowControl.y} ${legAxisX},${hipY} ${legAxisX},${hipY}`;
+}
+
+const RIGHT_LEG_REST_PATH = buildLegSvgPath(RIGHT_LEG_AXIS_X, rightLegBowControlStanding, HIP_Y_STANDING);
+const LEFT_LEG_REST_PATH = buildLegSvgPath(LEFT_LEG_AXIS_X, leftLegBowControlStanding, HIP_Y_STANDING);
+const RIGHT_LEG_COMPRESSED_PATH = buildLegSvgPath(RIGHT_LEG_AXIS_X, rightLegBowControlSquatting, HIP_Y_SQUATTING);
+const LEFT_LEG_COMPRESSED_PATH = buildLegSvgPath(LEFT_LEG_AXIS_X, leftLegBowControlSquatting, HIP_Y_SQUATTING);
+
+export function initCharacterJump() {
+ // Gravité constante — contrairement à un ressort, la force est uniforme :
+ // la chute accélère jusqu'au sol au lieu de ralentir en apesanteur
+ const GRAVITY = 900; // accélération vers le bas (unités SVG/s²)
+ const LAUNCH_VELOCITY = 225; // impulsion vers le haut (unités SVG/s)
+ const RESTITUTION = 0.15; // restitution du mini-rebond à l'atterrissage
+ const JUMP_CYCLE_DURATION_MS = 1200; // ms entre deux lancers
+ const SQUAT_DURATION_MS = 220; // durée du squat avant lancer
+ const LEG_EXTEND_DURATION_MS = 100; // extension des jambes juste après le lancer
+ const FOOT_MAX_ROTATION_DEG = 45; // rotation max des pieds (degrés)
+ const BODY_SQUAT_AMPLITUDE = HIP_Y_SQUATTING - HIP_Y_STANDING;
+
+ const rightCharacter = document.getElementById("right-character");
+ const rightCharacterBody = document.getElementById("right-character-body");
+ const rightLeg = document.getElementById("right-leg1");
+ const leftLeg = document.getElementById("left-leg1");
+ const rightFoot = document.getElementById("right-foot1");
+ const leftFoot = document.getElementById("left-foot1");
+
+ function interpolateSvgPath(startPath, endPath, interpolationFactor) {
+ const numberPattern = /-?\d+\.?\d*/g;
+ const startNumbers = startPath.match(numberPattern).map(Number);
+ const endNumbers = endPath.match(numberPattern).map(Number);
+ let numberIndex = 0;
+ return startPath.replace(numberPattern, () => {
+ const interpolatedValue =
+ startNumbers[numberIndex] +
+ (endNumbers[numberIndex] - startNumbers[numberIndex]) * interpolationFactor;
+ numberIndex++;
+ return interpolatedValue.toFixed(2);
+ });
+ }
+
+ const easeInOutQuadratic = (t) => (t < 0.5 ? 2 * t * t : 1 - (-2 * t + 2) ** 2 / 2);
+ const easeInQuadratic = (t) => t * t;
+
+ // Crée un ressort secondaire indépendant (fermeture sur position/vitesse)
+ function createSpringSimulator(stiffness, damping) {
+ let position = 0;
+ let velocity = 0;
+ return (target, deltaTime) => {
+ const acceleration = -stiffness * (position - target) - damping * velocity;
+ velocity += acceleration * deltaTime;
+ position += velocity * deltaTime;
+ return position;
+ };
+ }
+
+ // Cinématique verticale — position > 0 = en l'air
+ let verticalPosition = 0;
+ let verticalVelocity = 0;
+ let landingCompressionRatio = 0;
+
+ // Ressorts secondaires : chaque partie suit sa cible avec son propre délai
+ // Corps/tête : k élevé → réactif, léger overshoot sur le relâché
+ // Jambes : mêmes paramètres que le corps pour rester visuellement connectés
+ // Pieds : k bas → floppy, ils traînent naturellement
+ const bodySpring = createSpringSimulator(300, 18);
+ const legSpring = createSpringSimulator(300, 18);
+ const rightFootSpring = createSpringSimulator(150, 10);
+ const leftFootSpring = createSpringSimulator(150, 10);
+
+ let isHovered = false;
+ let isInJumpCycle = false;
+ let jumpCycleStartTime = null;
+ let hasLaunched = false;
+ let previousFrameTime = null;
+
+ const wrapper = document.querySelector(".characters");
+ wrapper.addEventListener("mouseenter", () => { isHovered = true; });
+ wrapper.addEventListener("mouseleave", () => { isHovered = false; });
+
+ function computeSquatCompressionRatio(elapsedCycleTime) {
+ if (elapsedCycleTime < SQUAT_DURATION_MS) {
+ return easeInOutQuadratic(elapsedCycleTime / SQUAT_DURATION_MS);
+ }
+ if (elapsedCycleTime < SQUAT_DURATION_MS + LEG_EXTEND_DURATION_MS) {
+ return 1 - easeInQuadratic((elapsedCycleTime - SQUAT_DURATION_MS) / LEG_EXTEND_DURATION_MS);
+ }
+ return 0;
+ }
+
+ function applyLandingBounce(impactVelocity) {
+ if (impactVelocity > 50) {
+ landingCompressionRatio = Math.min(0.6, (impactVelocity / LAUNCH_VELOCITY) * 0.8);
+ }
+ verticalVelocity = impactVelocity > 15 ? impactVelocity * RESTITUTION : 0;
+ }
+
+ function updateVerticalPhysics(deltaTime) {
+ if (verticalPosition > 0 || verticalVelocity > 0) {
+ verticalVelocity -= GRAVITY * deltaTime;
+ }
+ verticalPosition += verticalVelocity * deltaTime;
+
+ if (verticalPosition < 0) {
+ if (verticalVelocity < 0) {
+ applyLandingBounce(-verticalVelocity);
+ }
+ verticalPosition = 0;
+ }
+
+ landingCompressionRatio = Math.max(0, landingCompressionRatio - 4 * deltaTime);
+ }
+
+ function updateJumpCycle(currentTime) {
+ if (isHovered && !isInJumpCycle) {
+ jumpCycleStartTime = currentTime;
+ isInJumpCycle = true;
+ hasLaunched = false;
+ }
+
+ let elapsedCycleTime = isInJumpCycle ? currentTime - jumpCycleStartTime : 0;
+
+ if (isInJumpCycle && elapsedCycleTime >= JUMP_CYCLE_DURATION_MS) {
+ if (isHovered) {
+ jumpCycleStartTime = currentTime;
+ elapsedCycleTime = 0;
+ hasLaunched = false;
+ } else {
+ isInJumpCycle = false;
+ elapsedCycleTime = 0;
+ }
+ }
+
+ let squatCompressionRatio = 0;
+ if (isInJumpCycle) {
+ squatCompressionRatio = computeSquatCompressionRatio(elapsedCycleTime);
+
+ if (!hasLaunched && elapsedCycleTime >= SQUAT_DURATION_MS) {
+ verticalVelocity += LAUNCH_VELOCITY;
+ hasLaunched = true;
+ }
+ }
+
+ return squatCompressionRatio;
+ }
+
+ function applyTransforms(compressionTarget, deltaTime) {
+ const verticalTranslation = -verticalPosition;
+ const footRotationTarget = verticalPosition > 3 ? Math.min(1, (verticalPosition - 3) / 12) : 0;
+
+ const bodyVerticalDisplacement = bodySpring(compressionTarget * BODY_SQUAT_AMPLITUDE, deltaTime);
+ const legCompressionRatio = Math.max(0, Math.min(1, legSpring(compressionTarget, deltaTime)));
+ const rightFootRotationAngle = Math.max(0, rightFootSpring(footRotationTarget * FOOT_MAX_ROTATION_DEG, deltaTime));
+ const leftFootRotationAngle = Math.min(0, leftFootSpring(-footRotationTarget * FOOT_MAX_ROTATION_DEG, deltaTime));
+
+ rightCharacter.setAttribute("transform", `translate(0,${verticalTranslation.toFixed(2)})`);
+ rightCharacterBody.setAttribute("transform", `translate(0,${bodyVerticalDisplacement.toFixed(2)})`);
+ rightLeg.setAttribute("d", interpolateSvgPath(RIGHT_LEG_REST_PATH, RIGHT_LEG_COMPRESSED_PATH, legCompressionRatio));
+ leftLeg.setAttribute("d", interpolateSvgPath(LEFT_LEG_REST_PATH, LEFT_LEG_COMPRESSED_PATH, legCompressionRatio));
+ rightFoot.setAttribute("transform", `rotate(${rightFootRotationAngle.toFixed(1)},${RIGHT_LEG_AXIS_X},217.6)`);
+ leftFoot.setAttribute("transform", `rotate(${leftFootRotationAngle.toFixed(1)},${LEFT_LEG_AXIS_X},217.6)`);
+ }
+
+ function animateJump(currentTime) {
+ if (!previousFrameTime) previousFrameTime = currentTime;
+ const deltaTime = Math.min((currentTime - previousFrameTime) / 1000, 0.05);
+ previousFrameTime = currentTime;
+
+ const squatCompressionRatio = updateJumpCycle(currentTime);
+ updateVerticalPhysics(deltaTime);
+
+ const compressionTarget = Math.max(squatCompressionRatio, landingCompressionRatio);
+ applyTransforms(compressionTarget, deltaTime);
+
+ requestAnimationFrame(animateJump);
+ }
+
+ requestAnimationFrame(animateJump);
+}
diff --git a/assets/js/characters/pupilTracking.js b/assets/js/characters/pupilTracking.js
new file mode 100644
index 0000000..94974b1
--- /dev/null
+++ b/assets/js/characters/pupilTracking.js
@@ -0,0 +1,58 @@
+export function initPupilTracking(svg) {
+ const VIEWBOX_WIDTH = 304;
+ const VIEWBOX_HEIGHT = 259;
+ const PUPIL_SCALE = 1.267471;
+ const PUPIL_BASE_TRANSLATE_X = PUPIL_SCALE * 52.5;
+ const PUPIL_BASE_TRANSLATE_Y = PUPIL_SCALE * 87.5;
+ const PUPIL_MAX_OFFSET_RADIUS = 3.5;
+ const PUPIL_LERP_FACTOR = 0.12;
+
+ // Centre de chaque œil — personnage gauche uniquement
+ const eyes = [
+ { id: "left-pupil", centerX: 54.03, centerY: 86.79 },
+ { id: "right-pupil", centerX: 103.55, centerY: 86.79 },
+ ];
+
+ const currentPupilPositions = eyes.map((eye) => ({ x: eye.centerX, y: eye.centerY }));
+ const targetPupilPositions = eyes.map((eye) => ({ x: eye.centerX, y: eye.centerY }));
+
+ document.addEventListener("mousemove", (event) => {
+ const svgBoundingRect = svg.getBoundingClientRect();
+ const mouseViewportX = (event.clientX - svgBoundingRect.left) * (VIEWBOX_WIDTH / svgBoundingRect.width);
+ const mouseViewportY = (event.clientY - svgBoundingRect.top) * (VIEWBOX_HEIGHT / svgBoundingRect.height);
+
+ eyes.forEach((eye, eyeIndex) => {
+ const deltaX = mouseViewportX - eye.centerX;
+ const deltaY = mouseViewportY - eye.centerY;
+ const distanceToMouse = Math.hypot(deltaX, deltaY);
+ const clampRatio = distanceToMouse > 0 ? Math.min(PUPIL_MAX_OFFSET_RADIUS, distanceToMouse) / distanceToMouse : 0;
+ targetPupilPositions[eyeIndex].x = eye.centerX + deltaX * clampRatio;
+ targetPupilPositions[eyeIndex].y = eye.centerY + deltaY * clampRatio;
+ });
+ });
+
+ document.addEventListener("mouseleave", () => {
+ eyes.forEach((eye, eyeIndex) => {
+ targetPupilPositions[eyeIndex].x = eye.centerX;
+ targetPupilPositions[eyeIndex].y = eye.centerY;
+ });
+ });
+
+ function animatePupils() {
+ eyes.forEach((eye, eyeIndex) => {
+ currentPupilPositions[eyeIndex].x +=
+ (targetPupilPositions[eyeIndex].x - currentPupilPositions[eyeIndex].x) * PUPIL_LERP_FACTOR;
+ currentPupilPositions[eyeIndex].y +=
+ (targetPupilPositions[eyeIndex].y - currentPupilPositions[eyeIndex].y) * PUPIL_LERP_FACTOR;
+ document
+ .getElementById(eye.id)
+ ?.setAttribute(
+ "transform",
+ `matrix(${PUPIL_SCALE},0,0,${PUPIL_SCALE},${currentPupilPositions[eyeIndex].x - PUPIL_BASE_TRANSLATE_X},${currentPupilPositions[eyeIndex].y - PUPIL_BASE_TRANSLATE_Y})`
+ );
+ });
+ requestAnimationFrame(animatePupils);
+ }
+
+ requestAnimationFrame(animatePupils);
+}
diff --git a/assets/js/script.js b/assets/js/script.js
index e751723..a3c4453 100644
--- a/assets/js/script.js
+++ b/assets/js/script.js
@@ -1,21 +1,22 @@
-document.addEventListener("DOMContentLoaded", () => {
- const header = document.querySelector(".main-header");
- const charactersWrapper = document.querySelector(".characters");
- const logo = document.querySelector(".logo");
- const svg = charactersWrapper.querySelector("svg");
+import { initCharacterJump } from "./characters/jump.js";
+import { initPupilTracking } from "./characters/pupilTracking.js";
- const CHAR_SPEED = 0.6;
- const LOGO_SPEED = 1.2;
+document.addEventListener("DOMContentLoaded", () => {
+ const header = document.querySelector(".main-header");
+ const charactersWrapper = document.querySelector(".characters");
+ const logo = document.querySelector(".logo");
+ const svg = charactersWrapper.querySelector("svg");
+
+ const CHAR_SPEED = 0.6;
+ const LOGO_SPEED = 1.2;
const CHAR_WIDTH_MAX = 304;
const CHAR_WIDTH_MIN = 150;
// Valeurs initiales lues depuis l'attribut style HTML
- const charMax = parseFloat(
- charactersWrapper.style.getPropertyValue("--offset")
- );
+ const charMax = parseFloat(charactersWrapper.style.getPropertyValue("--offset"));
const logoMax = logo.offsetHeight + 100;
- let menuOpen = false;
+ let menuOpen = false;
let menuTransitioning = false;
function onScroll() {
@@ -33,10 +34,8 @@ document.addEventListener("DOMContentLoaded", () => {
function scaleCharacters(scrollY) {
const charOffset = Math.max(0, charMax - (scrollY / 16) * CHAR_SPEED);
- const charWidth =
- CHAR_WIDTH_MIN +
- (charOffset / charMax) * (CHAR_WIDTH_MAX - CHAR_WIDTH_MIN);
- svg.setAttribute("width", charWidth + "px");
+ const charWidth = CHAR_WIDTH_MIN + (charOffset / charMax) * (CHAR_WIDTH_MAX - CHAR_WIDTH_MIN);
+ svg.setAttribute("width", charWidth + "px");
svg.setAttribute("height", charWidth + "px");
}
@@ -50,23 +49,23 @@ document.addEventListener("DOMContentLoaded", () => {
{
const nav = {
toggleBtn: document.querySelector(".toggle-nav"),
- strip: document.querySelector(".strip"),
+ strip: document.querySelector(".strip"),
};
function openMenu() {
menuOpen = true;
header.classList.add("menu-transitioning", "big");
nav.strip.classList.add("open");
- nav.toggleBtn.textContent = "fermer";
+ nav.toggleBtn.textContent = "fermer";
document.body.style.overflow = "hidden";
}
function closeMenu() {
- menuOpen = false;
+ menuOpen = false;
menuTransitioning = true;
header.classList.remove("big");
nav.strip.classList.remove("open");
- nav.toggleBtn.textContent = "menu";
+ nav.toggleBtn.textContent = "menu";
document.body.style.overflow = "";
setTimeout(() => {
header.classList.remove("menu-transitioning");
@@ -78,14 +77,17 @@ document.addEventListener("DOMContentLoaded", () => {
nav.strip.classList.contains("open") ? closeMenu() : openMenu();
});
- document.addEventListener("keydown", (e) => {
- if (e.key === "Escape" && menuOpen) closeMenu();
+ document.addEventListener("keydown", (event) => {
+ if (event.key === "Escape" && menuOpen) closeMenu();
});
- document.addEventListener("click", (e) => {
+ document.addEventListener("click", (event) => {
if (!menuOpen) return;
- if (e.target.closest(".toggle-nav")) return;
- if (!e.target.closest(".strip")) closeMenu();
+ if (event.target.closest(".toggle-nav")) return;
+ if (!event.target.closest(".strip")) closeMenu();
});
}
+
+ initCharacterJump();
+ initPupilTracking(svg);
});
diff --git a/site/snippets/head.php b/site/snippets/head.php
index fd0ff2c..fd10360 100644
--- a/site/snippets/head.php
+++ b/site/snippets/head.php
@@ -7,6 +7,5 @@
-
-
+
\ No newline at end of file