◆ 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/horloge.js · 6.9 Ko

/* ============================================================
   horloge.js - le cadran et les aiguilles
   ============================================================
   Idée clé : on se place AU CENTRE du cadran avec translate(),
   et on dessine chaque aiguille "pointée vers le haut" ; il suffit
   ensuite de TOURNER le repère avec rotate() pour la placer.

   RAPPEL : rotate() travaille en RADIANS par défaut.
     un tour complet = TWO_PI (≈ 6,283) ; un demi-tour = PI.
   Avec une aiguille dessinée vers le haut (y négatif), l'angle 0
   correspond à "12 h" et l'angle augmente dans le sens des
   aiguilles d'une montre. Pratique !
   ============================================================ */

/* ------------------------------------------------------------
   lireHeure(heureSimulee)
   But : obtenir l'heure à afficher.
   - Si heureSimulee est un nombre (curseur de la page), on le
     convertit en heures / minutes / secondes.
   - Sinon on utilise les fonctions p5 hour(), minute(), second()
     qui lisent l'heure LOCALE de l'appareil.
   Paramètre : heureSimulee = nombre (ex. 14.5) ou null
   Retour : {h, m, s, decimal} avec decimal = heure en nombre
            décimal (14 h 30 -> 14.5)
   ------------------------------------------------------------ */
function lireHeure(heureSimulee) {
  if (heureSimulee !== null) {
    const h = floor(heureSimulee);                       // partie entière = heures
    const reste = (heureSimulee - h) * 60;               // la partie décimale, en minutes
    const m = floor(reste);
    const s = floor((reste - m) * 60);
    return { h: h, m: m, s: s, decimal: heureSimulee };
  }
  const h = hour();       // 0 à 23
  const m = minute();     // 0 à 59
  const s = second();     // 0 à 59
  return { h: h, m: m, s: s, decimal: h + m / 60 + s / 3600 };
}

/* ------------------------------------------------------------
   formaterDeuxChiffres(n)
   But : écrire 5 sous la forme "05" (pour afficher 09:05:03).
   p5 offre nf(n, 2) qui fait exactement cela.
   ------------------------------------------------------------ */
function formaterDeuxChiffres(n) {
  return nf(n, 2);
}

/* ------------------------------------------------------------
   dessinerGraduations(r, encre)
   But : dessiner les 60 petits traits du cadran (un plus long
         toutes les 5 graduations = les heures).
   Paramètres : r = rayon du cadran, encre = couleur des traits
   ------------------------------------------------------------ */
function dessinerGraduations(r, encre) {
  stroke(encre);
  for (let i = 0; i < 60; i++) {
    push();
    rotate(i * TWO_PI / 60);               // 60 positions autour du cercle
    const grand = (i % 5 === 0);           // % = reste de la division : vrai toutes les 5 graduations
    strokeWeight(grand ? r * 0.03 : r * 0.012);
    const longueur = grand ? r * 0.1 : r * 0.045;
    line(0, -r * 0.93, 0, -r * 0.93 + longueur);   // trait vertical près du bord haut
    pop();
  }
}

/* ------------------------------------------------------------
   dessinerChiffres(r, encre)
   But : écrire les chiffres 1 à 12 autour du cadran.
   Pour placer un chiffre sur le cercle, on utilise la
   trigonométrie : x = sin(angle) * rayon ; y = -cos(angle) * rayon
   (le signe "-" car y est orienté vers le bas).
   ------------------------------------------------------------ */
function dessinerChiffres(r, encre) {
  noStroke();
  fill(encre);
  textAlign(CENTER, CENTER);               // le texte est centré sur le point donné
  textSize(r * 0.15);
  for (let i = 1; i <= 12; i++) {
    const angle = i * TWO_PI / 12;
    text(i, sin(angle) * r * 0.74, -cos(angle) * r * 0.74);
  }
}

/* ------------------------------------------------------------
   dessinerAiguille(angle, longueur, epaisseur, couleur)
   But : dessiner UNE aiguille tournée de "angle" radians.
   Paramètres :
     angle     : 0 = vers le haut (12 h)
     longueur  : en pixels
     epaisseur : épaisseur du trait
     couleur   : couleur du trait
   push()/pop() isolent la rotation : elle ne touche pas aux
   autres aiguilles.
   ------------------------------------------------------------ */
function dessinerAiguille(angle, longueur, epaisseur, couleur) {
  push();
  rotate(angle);
  stroke(couleur);
  strokeWeight(epaisseur);
  strokeCap(ROUND);                        // extrémités arrondies
  line(0, longueur * 0.12, 0, -longueur);  // petite "queue" derrière le centre
  pop();
}

/* ------------------------------------------------------------
   dessinerHorloge(t, cx, cy, r, nuit)
   But : dessiner le cadran complet avec les trois aiguilles.
   Paramètres :
     t      : l'heure ({h, m, s}) renvoyée par lireHeure()
     cx, cy : centre du cadran dans le canevas
     r      : rayon du cadran
     nuit   : 0 (plein jour) à 1 (nuit) ; le cadran devient sombre la nuit
   ------------------------------------------------------------ */
function dessinerHorloge(t, cx, cy, r, nuit) {
  // Couleurs du cadran : claires le jour, sombres la nuit (mélange selon "nuit").
  const fondCadran = lerpColor(color(255, 250, 240, 225), color(18, 28, 58, 225), nuit);
  const encre = lerpColor(color(30, 40, 60), color(240, 240, 230), nuit);

  push();                                  // sauvegarde l'état de dessin
  translate(cx, cy);                       // (0, 0) = centre du cadran à partir d'ici

  // Disque du cadran
  stroke(encre);
  strokeWeight(r * 0.035);
  fill(fondCadran);
  circle(0, 0, r * 2);                     // circle(x, y, DIAMÈTRE)

  dessinerGraduations(r, encre);
  dessinerChiffres(r, encre);

  // Petit texte « ANTALAHA » et heure numérique
  noStroke();
  fill(encre);
  textAlign(CENTER, CENTER);
  textSize(r * 0.075);
  text('ANTALAHA', 0, -r * 0.38);
  textSize(r * 0.13);
  text(formaterDeuxChiffres(t.h) + ':' + formaterDeuxChiffres(t.m), 0, r * 0.42);

  // --- Calcul des angles ---
  // map(valeur, minAvant, maxAvant, minAprès, maxAprès) :
  // ici on convertit une durée en angle (0 à TWO_PI = un tour complet).
  // Aiguille des secondes : 60 s = un tour.
  const angleSecondes = map(t.s, 0, 60, 0, TWO_PI);
  // Aiguille des minutes : 60 min = un tour ; les secondes la font avancer en douceur.
  const angleMinutes = map(t.m + t.s / 60, 0, 60, 0, TWO_PI);
  // Aiguille des heures : 12 h = un tour (on utilise % 12 : 15 h -> 3 h) ;
  // les minutes la font avancer en douceur aussi.
  const angleHeures = map((t.h % 12) + t.m / 60, 0, 12, 0, TWO_PI);

  // L'ordre compte : la trotteuse est dessinée en dernier pour être au-dessus.
  dessinerAiguille(angleHeures, r * LONGUEUR_AIGUILLE_HEURE, r * 0.07, encre);
  dessinerAiguille(angleMinutes, r * LONGUEUR_AIGUILLE_MINUTE, r * 0.045, encre);
  dessinerAiguille(angleSecondes, r * LONGUEUR_AIGUILLE_SECONDE, r * 0.02, color(COULEUR_TROTTEUSE));

  // Pastille centrale
  noStroke();
  fill(COULEUR_TROTTEUSE);
  circle(0, 0, r * 0.09);

  pop();                                   // on revient à l'état sauvegardé (origine en haut à gauche)
}