◆ Portail Antalaha

Annuaire › Code ouvert

Horloge d'Antalaha - décor jour et nuit (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/sketch.js · 6.4 Ko

/* ============================================================
   sketch.js - le programme principal (setup + draw)
   ============================================================
   Un programme p5.js a deux fonctions spéciales que p5 appelle
   tout seul (on est en "mode global") :

     setup()  : appelée UNE SEULE FOIS au démarrage.
                On y crée le canevas et on prépare les données.
     draw()   : appelée en BOUCLE, environ 60 fois par seconde.
                On y redessine toute l'image à chaque tour.
                C'est ce qui crée l'animation.

   Autre fonction spéciale utilisée ici :
     windowResized() : appelée quand la fenêtre change de taille.
   ============================================================ */

/* ---------- Variables globales (partagées entre les fonctions) ---------- */
let etapes = [];            // couleurs du ciel, préparées dans setup()
let etoiles = [];           // positions des étoiles
let heureSimulee = null;    // null = heure réelle ; un nombre = heure choisie avec le curseur
let tailleCanvas = 400;     // côté du canevas carré, en pixels
let derniereSeconde = -1;   // pour ne mettre à jour le texte HTML qu'une fois par seconde

/* ------------------------------------------------------------
   calculerTaille()
   But : déterminer le côté du canevas pour qu'il s'adapte à la
         largeur disponible (responsive).
   Retour : un nombre de pixels, entre TAILLE_MIN et TAILLE_MAX.
   ------------------------------------------------------------ */
function calculerTaille() {
  const boite = document.getElementById('conteneur-canvas');
  // clientWidth = largeur actuelle de la boîte HTML qui contiendra le canevas.
  // On prend la plus petite valeur entre cette largeur et TAILLE_MAX,
  // puis on empêche d'aller sous TAILLE_MIN (constrain).
  const dispo = boite ? boite.clientWidth : windowWidth;
  return constrain(min(dispo, TAILLE_MAX), TAILLE_MIN, TAILLE_MAX);
}

/* ------------------------------------------------------------
   setup()
   But : préparer le programme (appelée une fois par p5).
   ------------------------------------------------------------ */
function setup() {
  tailleCanvas = calculerTaille();

  // createCanvas(largeur, hauteur) crée la zone de dessin.
  // .parent('id') la place dans l'élément HTML portant cet id.
  createCanvas(tailleCanvas, tailleCanvas).parent('conteneur-canvas');

  // Description pour les lecteurs d'écran (accessibilité).
  describe("Une horloge analogique devant la baie d'Antalaha. Le ciel, le soleil ou la lune et la mer changent de couleur selon l'heure.");

  frameRate(30);              // 30 images par seconde suffisent pour une horloge (économise la batterie)
  textFont(POLICE);           // police du système

  // color() n'est utilisable qu'APRÈS le démarrage de p5 : on prépare donc ici.
  etapes = preparerEtapes();
  etoiles = creerEtoiles(NB_ETOILES);

  brancherCommandes();
}

/* ------------------------------------------------------------
   draw()
   But : redessiner tout, à chaque image.
   Étapes : 1) lire l'heure  2) calculer les couleurs
            3) dessiner le décor  4) dessiner l'horloge
   ------------------------------------------------------------ */
function draw() {
  const t = lireHeure(heureSimulee);
  const couleurs = couleursPourHeure(t.decimal, etapes);

  // Le décor remplit tout le canevas (donc pas besoin de background()).
  dessinerDecor(t.decimal, width, height, couleurs, etoiles);

  // `width` et `height` sont des variables p5 : taille actuelle du canevas.
  // Le cadran est centré, un peu au-dessus du milieu pour laisser voir la mer.
  dessinerHorloge(t, width / 2, height * 0.47, width * RAYON_CADRAN, couleurs.etoiles);

  // On met à jour le texte de la page seulement quand la seconde change.
  if (t.s !== derniereSeconde) {
    derniereSeconde = t.s;
    mettreAJourTexte(t);
  }
}

/* ------------------------------------------------------------
   windowResized()
   But : adapter le canevas quand la fenêtre change de taille
         (rotation du téléphone, redimensionnement...).
   resizeCanvas() change la taille SANS recréer le canevas.
   ------------------------------------------------------------ */
function windowResized() {
  tailleCanvas = calculerTaille();
  resizeCanvas(tailleCanvas, tailleCanvas);
}

/* ------------------------------------------------------------
   mettreAJourTexte(t)
   But : écrire l'heure et la date en toutes lettres dans la page
         HTML (utile aux lecteurs d'écran, et pour le plaisir).
   Paramètre : t = {h, m, s}
   ------------------------------------------------------------ */
function mettreAJourTexte(t) {
  const phase = nomDeLaPhase(t.decimal);
  const origine = (heureSimulee === null) ? 'heure locale' : 'heure simulée';
  document.getElementById('texte-heure').textContent =
    formaterDeuxChiffres(t.h) + ' h ' + formaterDeuxChiffres(t.m) + ' min ' +
    formaterDeuxChiffres(t.s) + ' s - ' + phase + ' (' + origine + ')';

  // La date vient de l'objet JavaScript Date ; toLocaleDateString la met en français.
  document.getElementById('texte-date').textContent =
    new Date().toLocaleDateString('fr-FR', OPTIONS_DATE);

  // Le curseur suit l'heure réelle quand on n'est pas en simulation.
  if (heureSimulee === null) {
    document.getElementById('valeur-curseur').textContent = 'heure réelle';
    document.getElementById('curseur-heure').value = t.decimal;
  }
}

/* ------------------------------------------------------------
   brancherCommandes()
   But : relier le curseur et le bouton de la page à notre code.
   addEventListener('input', fonction) : "appelle cette fonction
   chaque fois que l'utilisateur déplace le curseur".
   ------------------------------------------------------------ */
function brancherCommandes() {
  const curseur = document.getElementById('curseur-heure');
  const bouton = document.getElementById('bouton-reel');

  curseur.addEventListener('input', function () {
    heureSimulee = parseFloat(curseur.value);   // texte -> nombre
    const t = lireHeure(heureSimulee);
    document.getElementById('valeur-curseur').textContent =
      formaterDeuxChiffres(t.h) + ' h ' + formaterDeuxChiffres(t.m);
    derniereSeconde = -1;                       // force la mise à jour du texte
  });

  bouton.addEventListener('click', function () {
    heureSimulee = null;                        // on repasse à l'heure réelle
    derniereSeconde = -1;
  });
}