◆ Portail Antalaha

Annuaire › Code ouvert

Pluviométrie mensuelle - tableau de bord (p5.js)

tutorial · Voir le site ↗
Connectez-vous pour copier ce site

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/graphiques.js · 5.1 Ko

/* ============================================================
   graphiques.js - l'histogramme et la courbe
   ============================================================
   Deux façons de dessiner les MÊMES 12 valeurs. Chaque fonction
   reçoit un paramètre "opacite" (0 à 1) : c'est ce qui permet le
   fondu enchaîné quand on bascule d'un mode à l'autre.
   ============================================================ */

/* ------------------------------------------------------------
   couleurPourValeur(valeur, opacite)
   But : colorer une barre selon sa valeur : bleu clair pour une
         petite pluie, bleu foncé pour une grosse pluie.
   Paramètres : valeur en mm ; opacite de 0 à 1
   Retour : un objet couleur p5
   ------------------------------------------------------------ */
function couleurPourValeur(valeur, opacite) {
  // Position de la valeur entre 0 et le maximum de l'axe (borné entre 0 et 1).
  const t = constrain(valeur / echelle.maxi, 0, 1);
  const c = lerpColor(color(COULEURS.barreClaire), color(COULEURS.barreFoncee), t);
  c.setAlpha(255 * opacite);       // setAlpha : transparence de 0 à 255
  return c;
}

/* ------------------------------------------------------------
   dessinerHistogramme(valeurs, opacite)
   But : dessiner une barre par mois.
   Paramètres :
     valeurs : tableau de 12 nombres (les valeurs ANIMÉES)
     opacite : 0 (invisible) à 1 (opaque)
   ------------------------------------------------------------ */
function dessinerHistogramme(valeurs, opacite) {
  const largeurBarre = zone.colonne * LARGEUR_BARRE;
  noStroke();

  for (let i = 0; i < 12; i++) {
    const v = valeurs[i];
    const xCentre = xCentreColonne(i);
    const yHaut = yDepuisValeur(v);                  // sommet de la barre
    const hauteurBarre = zone.y1 - yHaut;            // hauteur en pixels

    // La barre survolée devient orange, les autres suivent le dégradé bleu.
    if (i === indexSelection) {
      const c = color(COULEURS.survol);
      c.setAlpha(255 * opacite);
      fill(c);
    } else {
      fill(couleurPourValeur(v, opacite));
    }

    // rect(x, y, largeur, hauteur, rayonHG, rayonHD, rayonBD, rayonBG)
    // Les 4 derniers nombres arrondissent les coins : ici seulement ceux du haut.
    if (hauteurBarre > 0.5) {
      rect(xCentre - largeurBarre / 2, yHaut, largeurBarre, hauteurBarre, 4, 4, 0, 0);
    }

    // Sur les écrans larges, on écrit la valeur au-dessus de chaque barre.
    if (zone.colonne >= LARGEUR_COLONNE_VALEURS && opacite > 0.5) {
      fill(COULEURS.texte);
      textSize(11);
      textAlign(CENTER, BOTTOM);
      text(Math.round(v), xCentre, yHaut - 3);
    }
  }
}

/* ------------------------------------------------------------
   dessinerCourbe(valeurs, opacite)
   But : relier les 12 points par une courbe lisse, avec un
         point (cercle) à chaque mois.
   curveVertex() trace une courbe qui passe par les points ;
   il faut répéter le premier et le dernier point (ils servent
   de "guides" à la courbe).
   ------------------------------------------------------------ */
function dessinerCourbe(valeurs, opacite) {
  const c = color(COULEURS.courbe);
  c.setAlpha(255 * opacite);

  // Surface sous la courbe, très transparente : aide à "voir" le volume de pluie.
  const surface = color(COULEURS.courbe);
  surface.setAlpha(40 * opacite);
  noStroke();
  fill(surface);
  beginShape();
  vertex(xCentreColonne(0), zone.y1);
  for (let i = 0; i < 12; i++) vertex(xCentreColonne(i), yDepuisValeur(valeurs[i]));
  vertex(xCentreColonne(11), zone.y1);
  endShape(CLOSE);

  // La courbe elle-même
  noFill();
  stroke(c);
  strokeWeight(3);
  beginShape();
  curveVertex(xCentreColonne(0), yDepuisValeur(valeurs[0]));          // point guide (répété)
  for (let i = 0; i < 12; i++) {
    // constrain : la courbe lisse peut "dépasser" ; on l'empêche de passer sous l'axe.
    curveVertex(xCentreColonne(i), constrain(yDepuisValeur(valeurs[i]), zone.y0, zone.y1));
  }
  curveVertex(xCentreColonne(11), yDepuisValeur(valeurs[11]));        // point guide (répété)
  endShape();

  // Les points
  for (let i = 0; i < 12; i++) {
    const actif = (i === indexSelection);
    const cp = actif ? color(COULEURS.survol) : color(COULEURS.courbe);
    cp.setAlpha(255 * opacite);
    fill(cp);
    stroke(255, 255 * opacite);                  // liseré blanc autour du point
    strokeWeight(2);
    circle(xCentreColonne(i), yDepuisValeur(valeurs[i]), actif ? 12 : 8);
  }
}

/* ------------------------------------------------------------
   dessinerLigneMoyenne(moyenne)
   But : ligne pointillée de la moyenne pluriannuelle, pour
         comparer une année à la normale.
   Paramètre : moyenne = tableau de 12 nombres
   ------------------------------------------------------------ */
function dessinerLigneMoyenne(moyenne) {
  // On trace 11 petits segments pointillés entre les points consécutifs.
  noFill();
  for (let i = 0; i < 11; i++) {
    tracerPointilles(xCentreColonne(i), yDepuisValeur(moyenne[i]),
                     xCentreColonne(i + 1), yDepuisValeur(moyenne[i + 1]),
                     COULEURS.moyenne, 2);
  }
}