Terre en ASCII
Ouvrir le globe. Faites glisser pour changer de point de vue : la rotation automatique s’interrompt pendant le geste, puis reprend. Le zoom et le déplacement latéral sont désactivés. L’aperçu de l’accueil et les esquisses Three.js utilisent le même composant.
De l’image au texte
L’objet sous-jacent reste une sphère Three.js, et non une carte plane. Un shader lit deux textures : un masque distingue les océans des terres, tandis qu’une carte de relief fait varier la luminosité des terres. Les océans sont rendus en noir. Ce traitement visuel ne simule ni l’éclairage solaire ni l’alternance du jour et de la nuit.
AsciiEffect de Three.js rend ensuite la sphère, réduit l’image pour l’échantillonner et associe des caractères aux valeurs de luminosité. Le résultat visible est une grille de texte HTML. Le shader fournit l’image à échantillonner ; il ne dessine pas les caractères.
const effect = new AsciiEffect(renderer, ' .:-+*=%~@#01o', {
invert: true,
resolution: 0.16,
});
L’espace placé au début du jeu de caractères laisse les océans sombres vides. Les terres restent lisibles sans disque plein autour du globe. Certains angles ne montrent donc qu’une étroite bande de continents ; un hémisphère presque vide ne prouve pas que la rotation s’est arrêtée.
Les caractères diffèrent par leur forme et leur densité visuelle, ce qui rend les variations de luminosité perceptibles dans le texte. Des traits comme -, = et ~ peuvent former des bandes horizontales sur des zones de luminosité voisine. La police et l’espacement influencent aussi l’image : le tableau HTML contient une grille de caractères, et des bordures ou des fonds de cellules ordinaires perturberaient le dessin du globe.
Rotation et durée de vie
Le globe tourne à 0,28 radian par seconde, avec un rendu limité à environ 30 images par seconde. OrbitControls modifie la vue de la caméra pendant le glissement. Le globe utilise le même état pause/lecture et le même calcul du temps entre images que l’attracteur. Les deux démarrent leur mouvement à l’ouverture, indépendamment de la préférence de réduction des animations du navigateur. Le bouton Pause/Lecture commande directement le mouvement. Le glissement manuel reste possible pendant la pause.
Le dessin est suspendu hors écran et lorsque la page est masquée. Au démontage, le composant annule sa trame d’animation, déconnecte ses observateurs, retire ses écouteurs et libère contrôles, textures, géométrie, matériau et moteur WebGL.
Un conteneur non nul peut produire un échantillon vide
AsciiEffect calcule les dimensions d’échantillonnage avec floor(width × resolution) et floor(height × resolution). Limiter les dimensions externes à un pixel ne suffit donc pas : avec une résolution de 0,16, la largeur d’échantillonnage peut encore être nulle. L’appel à getImageData déclenche alors une erreur.
Le composant arrondit d’abord les dimensions d’affichage, puis attend qu’elles permettent chacune au moins un pixel d’échantillonnage avant de redimensionner et de dessiner. Vérifier avant l’arrondi laisse passer des valeurs comme 6,3 pixels : arrondies à 6, elles produisent encore un échantillon de taille nulle. Ce cas se présente lorsqu’un aperçu est masqué, qu’un onglet change ou que le navigateur recalcule la mise en page. Un redimensionnement valide ultérieur doit permettre au rendu de reprendre.
Après une modification, vérifiez plusieurs longitudes en mouvement, le glissement et son relâchement, le démarrage automatique avec la réduction des animations activée, la pause et la reprise, le masquage suivi d’une restauration et le passage à une autre expérience puis le retour. L’accueil démarre avec les réglages par défaut et permet de faire glisser le globe. Les panneaux de paramètres et les boutons de lecture sont masqués pour laisser de la place à l’image ; le titre ouvre la page de l’expérience avec toutes ses commandes. L’implémentation se trouve dans src/components/AsciiEarth/index.js ; les styles ne doivent pas ajouter de bordures ou de fonds de tableau à la grille de caractères.