Annuaire › Code ouvert
Code publié par son auteur, en lecture seule. « Copier dans mon espace » crée un nouveau site à vous (non publié) que vous pouvez modifier librement.
js/interaction.js · 5.3 Ko
/* ============================================================
interaction.js - souris, doigt et infobulle
============================================================
p5 appelle automatiquement certaines fonctions quand
l'utilisateur agit (si on les définit) :
mouseMoved() : la souris bouge (sans bouton enfoncé)
mouseDragged() : la souris bouge bouton enfoncé
mousePressed() : clic
touchStarted() : un doigt se pose sur l'écran
touchMoved() : le doigt glisse
Toutes déterminent le MÊME résultat : "quel mois est sélectionné ?"
(variable globale indexSelection ; -1 = aucun).
Variables p5 utiles :
mouseX, mouseY : position de la souris DANS le canevas
touches : tableau des doigts posés ; touches[0].x / .y
============================================================ */
/* ------------------------------------------------------------
indexDepuisPosition(px, py)
But : trouver quel mois se trouve sous un point du canevas.
Paramètres : px, py = coordonnées en pixels dans le canevas
Retour : un entier de 0 à 11, ou -1 si le point est hors du graphique
------------------------------------------------------------ */
function indexDepuisPosition(px, py) {
// Hors du canevas ?
if (px < 0 || px > width || py < 0 || py > height) return -1;
// Hors de la zone horizontale du tracé (dans les marges) ?
if (px < zone.x0 || px > zone.x1) return -1;
// Division par la largeur d'une colonne -> numéro de colonne.
// floor() arrondit vers le bas ; constrain() évite 12 si px == zone.x1.
return constrain(floor((px - zone.x0) / zone.colonne), 0, 11);
}
/* ------------------------------------------------------------
mettreAJourSelectionSouris()
But : mémoriser le mois sous la souris.
------------------------------------------------------------ */
function mettreAJourSelectionSouris() {
indexSelection = indexDepuisPosition(mouseX, mouseY);
}
/* ------------------------------------------------------------
mettreAJourSelectionTactile()
But : mémoriser le mois sous le (premier) doigt.
Si aucun doigt n'est posé, on ne change rien : la sélection
reste affichée après avoir levé le doigt (pratique sur mobile).
------------------------------------------------------------ */
function mettreAJourSelectionTactile() {
if (touches.length > 0) {
indexSelection = indexDepuisPosition(touches[0].x, touches[0].y);
}
}
// --- Fonctions appelées automatiquement par p5 ---
function mouseMoved() { mettreAJourSelectionSouris(); }
function mouseDragged() { mettreAJourSelectionSouris(); }
function mousePressed() { mettreAJourSelectionSouris(); }
function touchStarted() { mettreAJourSelectionTactile(); } // on ne renvoie pas false : la page peut défiler
function touchMoved() { mettreAJourSelectionTactile(); }
/* ------------------------------------------------------------
dessinerSurvol()
But : colorer en arrière-plan la colonne sélectionnée.
------------------------------------------------------------ */
function dessinerSurvol() {
if (indexSelection < 0) return;
noStroke();
fill(242, 160, 7, 38); // orange très transparent
rect(zone.x0 + indexSelection * zone.colonne, zone.y0, zone.colonne, zone.haut);
}
/* ------------------------------------------------------------
dessinerInfobulle(valeurs)
But : dessiner la bulle d'information près du mois sélectionné.
Paramètre : valeurs = valeurs ANIMÉES (pour que la bulle suive
le sommet de la barre pendant l'animation).
On affiche pourtant la valeur CIBLE (la vraie), pas la valeur
en train de grandir.
------------------------------------------------------------ */
function dessinerInfobulle(valeurs) {
if (indexSelection < 0) return;
const i = indexSelection;
const vraie = valeursCibles[i];
// Lignes de texte de l'infobulle
const lignes = [];
lignes.push(MOIS_COMPLETS[i] + (choixCourant === 'moyenne' ? ' (moyenne)' : ' ' + choixCourant));
lignes.push(Math.round(vraie) + ' mm');
if (choixCourant !== 'moyenne') {
const ref = moyenneSerie[i];
const ecart = Math.round((vraie - ref) / ref * 100);
lignes.push((ecart >= 0 ? '+' : '') + ecart + ' % par rapport à la moyenne');
}
lignes.push('valeur d\'illustration');
// Taille de la bulle : on MESURE la ligne la plus large avec textWidth().
textFont(POLICE);
textSize(12);
let largeurMax = 0;
for (const l of lignes) largeurMax = Math.max(largeurMax, textWidth(l));
const margeInt = 8;
const interligne = 16;
const w = largeurMax + margeInt * 2;
const h = lignes.length * interligne + margeInt * 2 - 4;
// Position : au-dessus du sommet de la barre, centrée sur la colonne,
// mais TOUJOURS à l'intérieur du canevas grâce à constrain().
const ancreX = xCentreColonne(i);
const ancreY = yDepuisValeur(valeurs[i]);
const bx = constrain(ancreX - w / 2, 4, width - w - 4);
const by = constrain(ancreY - h - 12, 4, height - h - 4);
// Fond arrondi
noStroke();
fill(COULEURS.infobulleFond);
rect(bx, by, w, h, 6);
// Textes : 1re ligne en gras, 2e ligne plus grande
fill(COULEURS.infobulleTexte);
textAlign(LEFT, TOP);
for (let k = 0; k < lignes.length; k++) {
textStyle(k <= 1 ? BOLD : NORMAL);
textSize(k === 1 ? 14 : 12);
text(lignes[k], bx + margeInt, by + margeInt - 2 + k * interligne);
}
textStyle(NORMAL);
}