characters : refacto clean code, découpage en modules ES
Noms de variables et fonctions explicites (sans abréviation), fonctions unitaires, paths SVG construits via template literals avec constantes nommées. Découpage en assets/js/characters/jump.js et pupilTracking.js, importés dans script.js. Clamp de la rotation des pieds pour éviter le bounce à l'atterrissage. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
e7b8bf7aa7
commit
967afa28c3
5 changed files with 277 additions and 243 deletions
58
assets/js/characters/pupilTracking.js
Normal file
58
assets/js/characters/pupilTracking.js
Normal file
|
|
@ -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);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue