Folio
Une planche Folio explique une idée de la même manière qu'un musée d'histoire naturelle explique un spécimen. Il y a un objet sur un socle, une clé numérotée à côté de lui, et des textes muraux qui vous apprennent à le regarder. L'objet ici est un instrument que vous inventez, tel qu'un banc, une balance, un métier à tisser ou un alambic, dont les pièces en fonctionnement exécutent l'idée. Les lecteurs peuvent le manipuler, et chaque lecture est calculée.
Trois engagements
- Mécanisme, pas métaphore. L'instrument doit exécuter l'idée, pas se tenir à côté d'elle comme une illustration. Avant de dessiner, écrivez une ligne : "Quand le lecteur fait X, la pièce Y bouge, et ce mouvement est Z dans l'idée."
- Une source unique de nombres. Un petit modèle pur calcule tout : angles d'aiguilles, niveaux de fluides, l'affichage, la clé, les tableaux. La page n'affiche que ce que le modèle renvoie, de sorte qu'aucun endroit ne peut être en désaccord.
- Une lecture guidée. Un bon dessin a encore besoin d'un guide. Chaque planche est livrée avec une clé, une lecture terme par terme, le fonctionnement complet, et un compte rendu honnête de ce qui a été simplifié.
Pour commencer
- Quatre planches de référence sont fournies avec le dépôt. Planche I (
examples/attention/, l'attention comme un banc d'essai) est le modèle pour les idées faites d'étapes discrètes et d'une formule. Planche II (examples/heart/, le cœur humain comme une double pompe) est le modèle pour tout ce qui se déroule dans le temps : une simulation intégrée à chaque image, un flux continu, des phases, et des graphiques redessinés après chaque cycle. Planche III (examples/grid/, un réseau électrique miniature) est le modèle pour l'électricité, le magnétisme et les flux d'énergie, et pour un banc construit à partir de machines autonomes plutôt que de bandes : une turbine, un générateur avec un rotor tournant, des transformateurs, des pylônes et une ville. Planche IV (examples/hashmap/, une table de hachage comme un bureau de tri) est le modèle pour les algorithmes et les structures de données, où l'idée est une séquence d'opérations discrètes : chaque opération (insérer, chercher, redimensionner) se développe en une courte liste d'actions chronométrées (soulever, porter, plonger pour comparer, transporter chaque carte vers un nouvel emplacement), jouées les unes après les autres, de sorte que le lecteur regarde l'algorithme faire chaque pas. Ouvrez d'abord la plus proche. - Le démarrage le plus rapide est de copier une planche de référence :
node scripts/new-plate.mjs <nom>créeexamples/<nom>/à partir de la Planche I. Ensuite, remplacez son modèle, sa scène et ses textes. Construire à partir d'une planche fonctionnelle est plus rapide et plus sûr que de partir de zéro. - Les styles d'exposition partagés se trouvent dans
kit/folio-page.css; lapage.htmld'une planche met/*CSS*/à l'intérieur de sa<style>et ajoute seulement ses propres règles. node scripts/build-site.mjsconstruit chaque planche plus la page de couverture (site/index.html) dansdocs/, un site web prêt pour GitHub Pages. Pour ajouter une planche, ajoutez son nom à la listePLATESdans ce fichier et une carte à la couverture.- Construisez n'importe quelle planche en un seul fichier autonome avec
node scripts/build.mjs examples/<nom> dist/<nom>.html. - Si seul ce fichier est installé (pas le dépôt), l'annexe à la fin contient la bibliothèque de dessin ; sauvegardez-la sous
folio-kit.js.
Une planche se compose de cinq fichiers :
| Fichier | Rôle |
|---|---|
folio-kit.js | la bibliothèque de dessin (partagée, jamais modifiée par planche) |
folio-live.js | les trois vues : scène, calque lumineux, orbite, commutateur de vue (partagé) |
model.js | le modèle pur ; place un objet sur window |
plate.js | l'instrument : géométrie statique, emplacements animés, entrées |
page.js | clé, contrôles, textes muraux, registre ; écoute la planche |
page.html | le socle et les styles, avec les espaces réservés /*KIT*/ /*MODEL*/ /*PLATE*/ /*PAGE*/ |
Phase A : le briefing (pas encore de dessin)
A1. Périmètre. Dites à l'utilisateur ce qu'il reçoit et combien de temps cela prendra approximativement, avant de commencer :
| Périmètre | Contenu | Durée typique |
|---|---|---|
| Esquisse | instrument + clé + affichage, pas de textes muraux | moins d'une heure |
| Planche | la page d'exposition complète (par défaut pour "expliquer X") | une heure et demie à trois heures |
| Série | plusieurs planches sur un même banc partagé, échelle et palette | convenez de la liste d'abord, puis une planche à la fois |
A2. Le modèle. Écrivez model.js avant toute partie visuelle. Rassemblez la formule réelle, les unités et les grandeurs. Renvoyez des objets simples : entrées en entrée, toutes les quantités que la page affichera en sortie. Exécutez-le dans Node et affichez quelques cas. Cherchez les cas limites maintenant (un ensemble vide, une ligne masquée, une valeur à la limite). Si quelque chose est inventé, comme des poids factices ou des données d'exemple, notez-le pour le texte mural "À propos de ce spécimen".
A2b. Modèles qui s'exécutent dans le temps. Quand l'idée est un processus (un battement de cœur, une file d'attente qui se vide, une courbe d'apprentissage), écrivez-la comme un état plus une fonction step(s, dt) et un read(s) qui renvoie tout ce qui est affiché. Ajustez les paramètres par rapport à des valeurs connues dans Node avant de dessiner, comme le fait la Planche II pour un adulte au repos (environ 115/80 mmHg, 70 mL par battement, 5 L/min). Continuez la simulation pendant que le dessin est hors écran, et sautez seulement la peinture ; sinon, la modification d'un contrôle plus bas dans la page gèle les nombres.
A3. L'instrument et sa table de correspondance. Cherchez un instrument issu du monde des laboratoires, des ateliers, des observatoires ou des imprimeries. Écrivez ensuite la table qui lie chaque terme à une pièce :
| Terme dans l'idée | Pièce de l'instrument | Ce que le lecteur peut voir |
|---|---|---|
| requête | un chariot sur un rail aérien | il se gare au-dessus du mot qui demande |
| score pondéré | un cadran par mot | position de l'aiguille |
| softmax | un réservoir scellé | les colonnes ne peuvent diviser que ce qu'il contient |
| masque | robinets avec capuchons | les mots suivants sont fermés |
| somme pondérée | un plateau de dépôt en couches | la longueur de chaque couche est un poids |
Chaque ligne a besoin d'une pièce, et chaque pièce majeure a besoin d'une ligne. Voici quelques correspondances fiables : un total fixe devient un réservoir, une bourse ou un sac de poids. Une comparaison devient un cadran, une balance ou un pied à coulisse. Une sélection devient une vanne, un interrupteur ou un levier d'aiguillage. Une accumulation devient des couches, une pile ou un compteur. Un ordre devient un rail, une grille ou une goulotte.
Phase B : le banc
B1. Inventaire. Listez les pièces avant de les placer. Visez 30 à 60 pièces. Regroupez-les par fonction : pièces de termes (issues de la table, répétées par élément), pièces de support (socle, pieds, poteaux, rails, colliers, supports), pièces de contrôle (sélecteurs, molettes moletées, leviers) et détails de montage (plaque de catalogue, étiquettes gravées, bandes d'échelle, vis). Une quantité exactement, celle dont il est question dans l'idée, obtient le rouge.
B2. Bandes. Utilisez des coordonnées du monde avec x le long du banc, y vers le spectateur et z vers le haut. Divisez le banc en bandes de profondeur de l'arrière vers l'avant, et donnez à chaque bande un type de pièce. La Planche I utilise rail, colonnes, robinets, collecteur, cadrans, plateau. Laissez un espace entre les bandes en unités du monde, car une pièce qui dépasse dans la bande suivante sera peinte dans le mauvais ordre. À l'intérieur d'une bande, dessinez du plus lointain au plus proche. Réglez la caméra (az près de -24 pour un banc long, el 30) et ajustez-la aux coins avec Folio.fit.
B3. Chaînes statiques, emplacements animés. Parcourez les bandes une fois et poussez les chaînes SVG dans une liste ordonnée. Partout où quelque chose bouge, poussez plutôt un emplacement nommé. Au moment du montage, la liste devient un SVG avec un <g> vide par emplacement. Chaque image d'animation ne redessine que les emplacements, à partir de valeurs lissées qui poursuivent les cibles du modèle. Le dessin s'arrête une fois que toutes les valeurs sont arrivées.
B4. Broches. Placez 6 à 10 broches numérotées directement sur les pièces qui portent l'idée, numérotées dans l'ordre qu'un novice devrait regarder. Les broches sont les seules marques posées sur le dessin. Tout autre texte est gravé dans une surface : noms sur les faces avant des blocs, nombres sur les échelles, une plaque de catalogue sur le socle.
Phase C : le montage
La page fait partie de l'explication. Construisez-la à partir de ces blocs, de haut en bas :
- En-tête. La série à gauche, la marque au centre, le numéro de planche à droite.
- Bloc-titre. Un titre d'affichage qui nomme l'idée comme l'instrument ("L'attention, comme un banc d'essai."), trois phrases sur ce qui se passe, et une petite liste de catalogue : Objet, Idée, Modèle, Catalogue.
- La planche montée. Un support en papier avec un cadre en incrustation très fin. Ses coins portent le numéro de planche, une légende courte, l'indice d'interaction et un affichage en direct.
- La clé. Une entrée par broche, donnant le nom de la pièce et une ligne sur ce qu'elle calcule, avec les maths en mono. Le survol d'une entrée met en évidence sa broche, et le survol d'une broche met en évidence son entrée.
- Au banc. Des boutons et curseurs ordinaires qui font ce que les propres boutons de l'instrument font.
- Texte mural I : lire la planche. Une colonne pour chaque terme, dans l'ordre où la formule est écrite : un chiffre romain, un verbe, le terme, deux phrases qui renvoient aux broches par numéro, et une boîte des nombres actuels.
- Texte mural II : le registre. Le fonctionnement complet pour l'état actuel, une ligne par élément. Cliquer sur une ligne sélectionne cet élément.
- Texte mural III : la vue d'ensemble. Tout ce dont l'instrument montre une tranche (la matrice complète, la séquence entière, chaque compartiment), et les variantes entre lesquelles le sélecteur choisit.
- Texte mural IV : à propos de ce spécimen. Trois notes : ce qui est calculé exactement, ce qui a été choisi à la main, et ce qui a été laissé de côté. Incluez-le toujours.
- Colophon. Qui a réalisé la planche et quelles polices de caractères elle utilise.
Les contrôles répondent au pointeur et au clavier : cliquer sur une station, les flèches font défiler, les chiffres choisissent une variante, les crochets tournent un bouton, une lettre bascule un interrupteur. Quand personne n'interagit, la planche se démontre lentement. Elle s'arrête au survol ou au focus, se repose quand on défile loin, et montre une image fixe en cas de mouvement réduit. L'affichage utilise aria-live.
Phase C2 : trois vues
Chaque planche offre le même instrument de trois manières, choisies à partir d'un petit commutateur dans le coin supérieur du support (SVG · WebGL · 3D). Le modèle, la clé et les textes muraux ne changent pas entre les vues ; seule la manière dont le banc est affiché change.
SVG est le dessin gravé décrit ci-dessus. C'est la vue par défaut et la seule qui doit toujours fonctionner.
WebGL dépose de la lumière sur le dessin sans le redessiner. La lumière vit dans un canvas au-dessus du SVG, et elle sait ce qui est visible grâce à un masque rendu à partir du dessin lui-même : light() clone le SVG, recolore chaque surface par rôle (rouge pour le sol, vert pour les récipients et tuyaux, bleu pour le verre, noir pour tout le reste), conserve l'ordre du peintre, et télécharge le résultat comme texture. Tout ce que le dessin cache, la lumière ne peut pas le toucher, donc aucune logique d'occlusion séparée n'est nécessaire. Donnez à chaque surface son rôle avec une classe (floor sur le socle, pad sur les récepteurs surélevés, pipe ou les classes sanguines sur les vaisseaux) et passez les règles de couleur comme maskCss.
À l'intérieur du shader, onPlane(vb, z) transforme un pixel en un point du monde sur un plan horizontal, project() fait le chemin inverse, et fall() trouve où la lumière à travers une pièce atterrit sur le sol (la lampe se trouve derrière le banc, donc les flaques tombent devant les pièces, là où le lecteur peut les voir). Utilisez la lumière pour la quantité du sujet uniquement :
- Planche I : le fluide de chaque colonne brille avec son poids, un faisceau de lumière ondulée va de chaque colonne à travers le banc, et des impulsions courent le long du collecteur, plus rapides pendant que les poids se déplacent.
- Planche II : des impulsions voyagent le long de chaque vaisseau au débit réel (le même volume accumulé qui déplace les marques de flux SVG), chaque chambre projette une lumière de la couleur de son sang, et les ventricules s'embrasent en se contractant.
Accumulez la lumière en couleur prémultipliée (addLight) et choisissez les couleurs par thème : reflets pâles et flaques saturées sur le papier (mélange normal), lueurs plus vives sur le sol sombre (mélange écran, défini par le jeton --light-blend). Rendu uniquement lorsque la vue est active et que la planche est à l'écran, limitez le rapport de pixels à 1,5, et dessinez une seule image fixe en cas de mouvement réduit.
3D tourne le banc complètement autour. Comme toute la scène est une fonction de la caméra, stage.mount(az, el) la reconstruit simplement à partir du nouvel angle : chaque face est ré-ombrée par son orientation, chaque pièce ronde est re-silhouettée, chaque hachure est ré-espacée, et chaque étiquette gravée est re-projetée. L'ordre du peintre doit tenir de tous les côtés, donc ne codez jamais en dur "d'arrière en avant" :
- Enveloppez chaque bande de profondeur comme
{ y, draw }et passez la liste àapi.bands(list); il les trie du plus lointain au plus proche pour la caméra actuelle. Par derrière, la bande avant est dessinée en premier. - À l'intérieur d'une bande, ou pour un banc de machines séparées, donnez à chaque unité une position dans le monde et utilisez
api.units(list)avec{ at: [x, y, z], draw }. La Planche III est entièrement construite de cette manière. - Les parois d'un récipient ouvert (un plateau, un réservoir) sont ordonnées avec
api.backIsFaretapi.leftIsFar. - Tout ce qui est monté sur une face du socle (une plaque de catalogue en laiton, une came de synchronisation sur un panneau avant) n'est dessiné que lorsque cette face regarde vers le lecteur : vérifiez d'abord le signe de
cam.view.faceTexts'auto-élimine déjà.
orbit({ wrap: true }) permet à l'azimut de dépasser 360°, stage réajuste l'échelle à chaque angle (limité par orbitScale, de sorte que le banc ne saute jamais en taille), un double-clic ramène à la vue par défaut, et Maj avec les touches fléchées le tourne depuis le clavier. Vérifiez avec une grille d'angles tous les 45° à deux élévations. Une reconstruction complète de la Planche II prend environ 27 ms, ce qui est assez fluide pour être glissé ; si une planche est beaucoup plus lourde, mémorisez la dernière sortie de chaque emplacement et repeignez uniquement ce qui a changé, comme le fait la Planche III.
Quitter la 3D ramène la caméra à la vue par défaut, de sorte que la lumière WebGL (qui la suppose) s'aligne toujours.
Phase C2b : intérieurs mobiles
Une planche ne devrait jamais être une image fixe avec des nombres à côté. Trouvez les pièces qui bougeraient vraiment et pilotez-les à partir du modèle, à une vitesse que l'œil peut suivre :
- Les choses qui tournent. Une roue de flux dans un voyant tourne au débit réel (le collecteur de la Planche I), les cames de synchronisation tournent une fois par cycle et montrent quelle phase est active (Planche II), et le rotor d'un générateur, une roue à eau et un régulateur à boules tournent à la vitesse de la machine (Planche III). Accumulez l'angle à partir du modèle (
rot += ω·dt) plutôt qu'à partir de l'horloge, de sorte qu'une machine qui ralentit ralentisse visiblement. - Les choses qui se déplacent. Niveaux, pistons, valvules, aiguilles, les boules d'un régulateur qui s'écartent à mesure que la vitesse augmente, une lame de disjoncteur qui se lève.
- Les choses qui interagissent. Le mouvement d'une pièce en actionne une autre : un piston pompant déplace le fluide, un niveau qui monte pousse une palette, un levier qui bascule à un seuil. Vérifiez ces interactions dans le modèle pur avant de les dessiner, avec
node model.js --test. - Les choses qui s'allument. Les voyants lumineux (verts, jaunes, rouges) sur les panneaux s'allument selon la phase ou le statut. La Planche III allume des lampes sur les pylônes et le poste de transformation électrique lorsque le courant passe.
Les intérieurs mobiles n'ont besoin que d'un seul nombre supplémentaire par pièce : un angle, un déplacement, un niveau, une couleur. Conservez-les sur l'objet d'état du modèle et lisez-les dans plate.js via model.read(). Ne dupliquez pas la logique d'animation ; le modèle décide ce qui bouge et à quelle vitesse. plate.js ne fait que lisser (ease(number, target, rate)) et attribuer.
Phase D : la publication
D1. Palette et peau. Associez chaque planche au thème de couleur de sa série, qui comprend un fond (clair pour le papier, foncé pour le tableau de bord de la machine), des couleurs pour l'acier, le laiton, le bois, la pierre, le verre et les fluides, une ligne de surbrillance, une couleur d'arrière-plan pour la planche, et une couleur de texte. La Planche I utilise le thème Papier (hors-la-loi léger, blanc crème), la Planche II le thème Cuivre (cuivre et écume de cuivre), la Planche III le thème Réseau (étain et rouge pâle) et la Planche IV le thème Régime (bois et papier brun).
D2. Le colophon. Chaque planche imprime en bas : "Planche X de la série Y.”, puis la date, le type de machine (le banc), la fonction de tirage ("Gravure et lumière."), les polices ("Pitch Sans, Pitch Sans Display, Lapture.") et une courte signature.
D3. Construction pour le web. scripts/build.mjs produit un fichier HTML unique, autonome, qui fonctionne sans réseau. Il collecte et inline le CSS partagé de la planche, le CSS spécifique, le JS (pas d'imports externes, pas de modules), et assemble les espaces réservés. Utilisez node scripts/build.mjs examples/attention dist/attention.html et testez en ouvrant le fichier localement et en le servant via HTTPS pour le WebGL (les origines locales ne donnent pas les textures WebGL).
D4. Ajout de style. Pour les panneaux qui ne sont pas des planches (les pages d'une série, les pages de catalogue), tapez new-panel.mjs de manière similaire, mais avec seulement page.html et page.js sans modèle. Un panneau montre plusieurs planches ou un tableau de bord qui n'est pas un spécimen.
Annexe : l'API de dessin (folio-kit.js)
folio-kit.js exporte un objet Folio sur window avec les méthodes suivantes :
Folio.bands(list)– Ordonne une liste d'objets{ y, draw }du plus lointain au plus proche pour la caméra actuelle.Folio.units(list)– Commebandsmais pour des objets{ at:[x,y,z], draw }, triés par distance à partir de la caméra.Folio.backIsFar/Folio.leftIsFar– Pour les parois d'un récipient ouvert ; sélectionne l'ordre de dessin en fonction de l'angle de la caméra.Folio.faceText(text, x, y, z)– Place un texte gravé à un point 3D ; il s'affiche uniquement si la face (définie par la normale au point) regarde vers la caméra.Folio.fit(corners, padding)– Calcule la caméra pour encadrer un ensemble de coins 3D.Folio.ease(current, target, rate)– Retourne une valeur lissée qui se rapproche de la cible ; taux ~0,1 est doux.Folio.orbit(options)– Configure l'orbite 3D avec la souris/le toucher.Folio.light()– Configure la couche WebGL.Folio.stage.mount(az, el)– Redessine toute la scène depuis un angle donné.
Toutes les coordonnées 3D sont en unités du monde (un cube d'environ 10 unités de côté). Les angles sont en degrés. Les chaînes SVG sont construites avec des balises XML simples ; les attributs sont passés comme des chaînes de caractères.
Termes de service
Ce dépôt est fourni pour être utilisé avec Claude Code ou d'autres agents IA qui peuvent exécuter les scripts et construire les planches. Les exemples sont destinés à être modifiés et adaptés. Envoyez des corrections, des idées de planches et des rapports de bogues via le dépôt.