Communitygithub.com

GA-MO/iso

Créez des illustrations isométriques animées pour produits, dans un style premium d'outils de développement (dalles arrondies, piles de couches, fils avec impulsions lumineuses, étiquettes, boucle explicative), entièrement en SVG + CSS/WAAPI sans bibliothèque d'animation.

Qu'est-ce que iso ?

iso est un kit conçu pour générer des explications visuelles animées en isométrie, destinées aux pages de produits techniques, aux documentations ou aux démos d'outils de développement. Il produit du SVG et du HTML réels, sans aucune dépendance d'animation externe. Le kit propose une variété de mises en page (large, diagonale, panneaux, radiale, champ, explosée, objet) et des motifs de mouvement prêts à l'emploi (arrivées, connexions, remplissages, choix, survols) avec des timings précis. Chaque scène raconte une histoire en une boucle de 6 à 14 secondes, avec une intro, et s'adapte parfaitement aux écrans de téléphone et de bureau. Il inclut un ensemble complet d'outils de développement (rendu, capture d'écran, test de performance, contraste) pour garantir une qualité professionnelle. Le kit est particulièrement utile pour les ingénieurs et designers qui souhaitent créer des animations explicatives rapides, légères et performantes sans recourir à des outils complexes comme Rive ou After Effects.

Compatible avec~Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/GA-MO/isokit/tree/HEAD/skill

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

iso : explications isométriques animées

Une scène raconte une histoire de produit en une boucle de 6 à 14 secondes : les éléments arrivent, la lumière voyage entre eux, une partie s'allume à la fois, et la boucle revient à son premier plan. Un flux n'est qu'une seule forme. Choisissez la forme dont l'histoire a besoin dans le tableau des temps : une boîte qui s'ouvre pour montrer ses couches, un transfert entre deux objets, une grille qui se remplit, une pile qui fait pivoter un choix, ou des tuiles que le spectateur soulève en survolant. Tout est du vrai SVG et HTML textuel, s'adapte à sa boîte, se met en pause hors écran et se fige pour les mouvements réduits.

Le kit se trouve à côté de ce fichier :

  • lib/iso.ts: le constructeur Scene (projection, dalles, faces, fils, impulsions, étiquettes, pistes de mouvement), scene.exportSvg(), responsive() et lazyBox().
  • lib/runtime.ts: joue une scène rendue avec WAAPI, démarre son intro une fois que 40 % de celle-ci (ou la moitié de la hauteur de l'écran, pour une scène haute) est visible, la met en pause hors écran, supprime ses animations une fois qu'elle est à plus d'un demi-écran et les replace sur la même image avant son retour, la fige pour les mouvements réduits, expose window.isoSeek(t).
  • scripts/render.ts: rend un module de scène (export par défaut Page) en un seul fichier HTML autonome avec le runtime intégré.
  • scripts/shots.mjs: prend des captures d'écran de n'importe quelle page à des moments et largeurs choisis et écrit sheet.png.
  • scripts/check.ts: vérification stricte des types des fichiers de scène sur le disque par rapport au kit (bun scripts/check.ts scene.ts).
  • scripts/page-idle.mjs: fait défiler une page avec plusieurs scènes une fois, puis s'arrête à 0, 20, 35, 50, 60 et 80 % et imprime le temps du thread principal à chaque étape, avec le CPU à 1x et 4x (node scripts/page-idle.mjs page=<url> width=393 dpr=3 scroll=4). Exécutez-le sur toute page avec plus de quelques scènes.
  • scripts/perf.mjs: joue une page dans Chrome à une largeur de téléphone avec le CPU limité (node scripts/perf.mjs page=<out.html> width=393 throttle=4 seconds=20) et imprime le taux de trames, les percentiles de temps de trame, les trames tardives, les longues tâches et le temps du thread principal. Exécutez-le sur toute scène avec 30 objets en mouvement ou plus.
  • scripts/contrast.mjs, scripts/render-all.ts: mesure chaque texte dans une page rendue par rapport aux pixels juste derrière ses glyphes à l'image fixe et à quatre autres moments, et échoue en dessous de 4.5:1 (node scripts/contrast.mjs <out.html>; bun scripts/render-all.ts <dir> écrit d'abord chaque exemple du catalogue). Exécutez-le sur chaque scène avant de la déclarer terminée.
  • scripts/study-rive.mjs, scripts/compare-rive.mjs: outils facultatifs pour étudier une animation .riv de votre propre cadre par cadre et la comparer avec une scène du kit. Les deux ont besoin de runtime=<dossier avec canvas_advanced.mjs et rive.wasm>.
  • examples/: 64 scènes pour des produits fictifs, chaque fichier exporte example (title, story, prompt, level, category, layout, interaction, et art : les scènes compacte et large de art(compact, wide, breakpoint)) et une Page par défaut, donc scripts/render.ts rend n'importe laquelle d'entre elles. Une scène spot est une petite scène unique, art(compact). hero.ts exporte hero (un Art) et material-gallery.ts exporte galleries (un Art par famille de finition), chacun avec une Page par défaut. examples/shared.ts contient les surfaces, les rampes de couleurs, paints, les polices et fitX(), qui garde une étiquette à l'intérieur de sa scène sur la carte la plus étroite où elle se trouvera.

Choisissez l'exemple le plus proche de votre histoire et lisez-le avant de dessiner :

ExempleNiveauMontre
notifications.tssimplele fichier minimal : un noyau se ramifiant en trois tuiles, impulsions, flash d'arrivée et saut. Lisez-le d'abord
ci-deploy.tssimpleun paquet sautant le long d'une chaîne, un écrasement à l'atterrissage, une couleur d'état uniquement à la fin
file-upload.tssimpledes morceaux remplissant une barre de progression, puis des copies s'étendant vers des points de bord ; des tirets marchant sur les emplacements vides
db-branching.tssimpleun fantôme en pointillé qui devient solide, une tuile de changement qui glisse en arrière et fusionne
service-map.tssimplesurvol : neuf tuiles slab({ hover }) avec des étiquettes révélées au survol ou au tap, plus une boucle qui raconte toujours l'histoire
auth-flow.tsmoyenun téléphone panel() vertical, une saisie tapée, des fantômes de transfert transportant un jeton
etl-pipeline.tsmoyendes tuiles source alimentant un noyau le long de fils qui se dessinent avec elles, puis une grille qui se remplit et se vide ; des superpositions regroupées avec la dalle sur laquelle elles reposent pour qu'elles bougent ensemble
queue-workers.tsmoyenune file d'attente de slots pilotée par une table d'événements que la build valide (pas de débordement, pas de prise à partir de vide)
search-index.tsmoyendes tuiles en ligne sur une page claire, une requête tapée, des correspondances s'allumant, des résultats classés s'élevant
feature-flags.tsmoyenjeu : un vrai <button> dans une étiquette et un script intégré qui rejoue une étape de boucle avec seek
agent-tools.tscomplexeun noyau avec des satellites, des impulsions d'appel et de réponse, une carte de réponse qui tape
checkout-payment.tscomplexeun anneau d'étapes avec un chemin de retour en pointillé et une ligne d'état qui s'estompe
edge-cache.tscomplexela même requête deux fois : un échec chaud vers l'origine, puis un succès froid en périphérie
observability.tscomplexetrois aspects de signal (tirets, points, plages), des barres prism avec heightTo, une alerte et une récupération
keycard-slot.ts, battery-charge.ts, tile-loader.ts, empty-box.tsspotun petit objet pour une liste de fonctionnalités, un chargeur ou un état vide ; une carte panel() verticale coupée à la lèvre d'un slot, des cellules heightTo, une vague de chute diagonale, des tirets marchants
sync-loop.ts, inbox-fill.ts, alert-stack.ts, table-scan.tsspotdes flèches écrasées sur le plan, un plateau à façade vitrée, des cartes glissant sur une pile avec un badge qui compte et chevauche la carte du dessus, une lentille glissant ligne par ligne
audit-ledger.ts, dns-resolve.ts, cron-jobs.tssimpledes pages s'empilant avec des sceaux, un saut à la fois avec des réponses, un cadran qui déclenche des tâches
vault-rotate.ts, firewall-filter.ts, zero-trust.tsmoyenun échange de clé avec le motif de slot, un paquet rejeté rebondissant, chaque requête estampillée
workload-scheduler.ts, autoscale.ts, health-check.tsmoyenplacement à partir d'une petite table de règles, faire de la place pour un nouveau nœud, un nœud retiré et réintégré
blue-green.ts, snapshot-restore.tsmoyenun fil re-ciblé, un curseur glissant en arrière le long d'une chronologie
embedding-clusters.ts, training-loss.ts, recs-rerank.ts, ab-test.tsmoyendes points se stabilisant en grappes, des barres prism tombantes, une étagère de slot se réordonnant, une division avec un gagnant
data-erasure.ts, rag-answer.tscomplexeune requête se ramifiant vers six systèmes avec un compteur, des cartes récupérées volant dans un modèle et une réponse tapant
hero.tscomplexeune invite fait croître un système en niveaux de 1, 5, 15 et 40 : une rotation d'entrée et une chute pondérée, des sorties glissant de dessous, des pops, un bassin qui tombe avec un remplissage de grille, des requêtes infinies, une inclinaison vers la souris au repos ; des flashs par fill et des tuiles répétées par <use> pour rester économique ; seulement du SVG text(), donc exportSvg() fonctionne dessus
funnel-live.ts, billing-cycle.ts, parcel-delivery.ts, test-shards.tsmoyen, complexelayout: 'wide' : bandes 3:1 lues de gauche à droite (étapes se rétrécissant, une bande de mois qui se décale sans saut, des véhicules transportant une boîte, des fragments courant dans des couloirs et fusionnant)
kanban-move.ts, stock-sync.ts, diff-merge.ts, refund-flow.tssimple à complexelayout: 'diagonal' : une carte ou un jeton voyageant le long d'un axe isométrique, des portes devenant vertes, un remboursement parcourant le même chemin en une seconde couleur
live-cursors.ts, two-approvals.ts, design-comments.ts, translate-six.tssimple, moyenlayout: 'panels' : des panel() verticaux se faisant face ; des curseurs tapant, deux coches déverrouillant un cadenas, des épingles et un fil, un message en six langues avec une pile de polices thaï et japonaise
cms-publish.ts, sensor-gateway.ts, smart-home.ts, currency-convert.tssimple, moyenlayout: 'radial' : une copie vers cinq canaux, des lectures entrant puis une vague de sol sortant, des appareils changeant d'état tour à tour, une impulsion faisant une fois le tour d'un fil en anneau
ota-rollout.ts, build-cache.ts, calendar-booking.ts, load-slider.tssimple à complexelayout: 'field' : des vagues à travers un champ d'appareils avec un arrêt et une nouvelle tentative, des succès de cache calculés à partir d'une table de dépendances, une réunion évitant un conflit ; load-slider est un contrôle de glissement (un vrai champ de saisie intervalle, souris, tactile et clavier) qui cherche la boucle tandis que le trafic ambiant continue de bouger
video-transcode.ts, image-resize.ts, fraud-gauge.ts, data-lineage.ts, drill-down.tssimple à complexelayout: 'exploded' : des rendus se soulevant et s'encodant, des tailles se décolant, des couches de risque s'ajoutant au-delà d'une ligne, un chemin amont s'allumant à travers des couches ; drill-down ouvre une partie dans ses couches à partir d'un vrai bouton en cherchant le segment de boucle de cette partie
materials-*.ts, material-gallery.ts49 finitions de côté dans six familles (Métal, Verre, Naturel, Motif Tech, Rétro, Générative) en tant que fabriques (scene) => Material, une galerie sans étiquette par famille. Les finitions génératives prennent une graine. Copiez une finition plutôt que d'en inventer une

Configuration unique : cd <ce dossier>/scripts && bun install && bunx playwright install webkit (les captures d'écran utilisent Google Chrome installé pour Chromium). Vérification de type : scripts/node_modules/.bin/tsc -p <ce dossier>.

1. Storyboard avant de dessiner

Ouvrez d'abord recipes.md. Il contient tous les motifs de mouvement et de composition mesurés (arrivées, connexions, flux, comparaisons, choix, inactif, interaction, easings, surfaces), chacun avec ses nombres et appels au kit. Composez l'histoire à partir de ces recettes et conservez leurs minutages.

Écrivez d'abord l'histoire sous forme de tableau chronologique : ce que le spectateur doit comprendre, les 3 à 6 temps qui le montrent, et pour chaque temps quel élément bouge, comment, quand et pendant combien de temps. Une idée par temps. Un temps qui nécessite un paragraphe pour s'expliquer est deux temps ou la mauvaise image.

Formes de temps éprouvées, avec des minutages mesurés :

TempsCe qui se passeMinutage
ArriverLes pièces tombent une par une, dépassent un peu, se stabilisentdropIn : 0,55 s chacune, 83 ms de décalage, 46 px de chute
TransfertDes contours fantômes d'une tuile glissent d'un objet à un autre4 fantômes, 0,22 s d'écart, 1,2 s chacun, ease.io
VoyagerUne courte impulsion lumineuse court le long d'un fil ; la cible clignote à l'arrivée270 px/s, impulsion ~0,12 à 0,16 du fil, montée 0,1 s, fondu 0,6 s
Révéler les couchesUne boîte solide devient transparente ; les couches intérieures s'allument une à la fois avec une étiquetteallumage 0,23 s, maintien ~1 s, extinction 0,2 s, la suivante commence à la fin de la dernière
Faire pivoter le choixUne pile monte d'un cran ; la carte active devient d'une couleur d'accent0,9 s de déplacement toutes les 3 s, démarrage lent, longue sortie en douceur
Remplir et viderUne grille se remplit tuile par tuile, tient, retombe à vide7 images (0,12 s) d'écart à l'entrée, 2 images d'écart à la sortie
TirerQuand un fil rétrécit ou grandit, la boîte à laquelle il est attaché est tirée d'environ 6 px le long du fil, tient, puis revient en douceur, donnant l'impression que le fil a une tension0,23 s de traction, 0,25 s de maintien, 0,65 s de retour avec une longue sortie en douceur
Soulever au survolUne tuile s'élève de 16 px et prend sa couleur de marque, son nom apparaîtslab({ hover }) : 270 ms d'activation, 325 ms de désactivation, ease.out

Règle de connexion : un fil est à l'écran seulement lorsque ses deux extrémités le sont. Un fil vers quelque chose qui arrive au milieu de la boucle se dessine avec son impulsion (wire({ dash: '1 1' }), puis at(id, 'strokeDashoffset', t, d, 1, 0, ease.linear)) et part avec la chose qu'il rejoint. Ne mettez jamais un tel fil dans l'intro. Un fil ne traverse jamais la face supérieure d'une boîte : ajoutez-le avant les objets qu'il rejoint (afin qu'ils le peignent par-dessus) et commencez-le au bord de la boîte, pas à son centre.

Règle de boucle : la dernière image égale la première. Tout ce qui change pendant la boucle change en retour avant la fin. Le mouvement de l'intro va dans intro() ; la boucle commence quand l'intro se termine, et l'intro doit se terminer sur la même image que celle par laquelle la boucle commence. Un élément sans intro montre la valeur de départ de la boucle pendant l'intro, qui est le dernier to de ses segments de boucle.

L'ordre de peinture est fixe : ce qui est ajouté plus tard recouvre toujours ce qui a été ajouté plus tôt. Un mouvement qui changerait qui recouvre qui (une carte passant du haut de la pile au bas) est dessiné sous forme de slots à la place. Chaque élément est un slot qui se déplace d'un pas et s'estompe ou se recolore comme son voisin, et chaque segment recommence à partir de la valeur de repos du slot, donc tous les slots sautent en arrière ensemble tandis que l'image semble la même. Donnez à chaque slot une étiquette par option et faites un fondu entre elles pour montrer celle qui est à côté du slot actif.

2. Choisissez une mise en page, puis composez d'abord pour le téléphone

Chaque exemple nomme sa composition dans layout : wide (une longue bande lue de gauche à droite ; sa scène large est d'environ 3:1, comme 1200x400, avec un point de rupture de 720, et la vitrine la montre comme une carte pleine largeur), diagonal (une longue rangée le long d'un axe isométrique), panels (des panel() verticaux se faisant face), radial (un noyau avec des choses sur un anneau), field (plusieurs tuiles vues de haut ; un ratio légèrement plus raide aide), exploded (des couches soulevées verticalement) ou object (un ou deux objets pour une liste de fonctionnalités ou un état vide). Choisissez celle dont l'histoire a besoin avant de dessiner ; une page de scènes se lit mieux quand elles varient.

Une scène que le spectateur peut jouer (interaction: 'play' | 'drag' | 'explore') livre un petit script de module intégré dans art()'s head : vrai <button> ou <input type="range"> dans une label({ html }), événements de pointeur pour la souris et le tactile (touch-action: none sur un contrôle de glissement), les touches aussi, un MutationObserver pour lier les scènes qui se montent plus tard, la boucle en pause pendant que le spectateur agit et reprise après quelques secondes d'inactivité, et une boucle qui raconte toujours l'histoire sans entrée (feature-flags.ts, load-slider.ts, drill-down.ts).

Les pages de stand et d'atterrissage sont ouvertes sur des téléphones. Construisez deux scènes et enveloppez-les avec responsive(compact, wide) :

  • compact : environ 390 de large, portrait ou carré (390x420 à 390x640). Empilez l'histoire de haut en bas. Concevez en unités 390 pour qu'une étiquette size: 13 fasse 13 px sur un téléphone. Jamais en dessous de 13.
  • wide : environ 900 à 1200 de large, paysage, l'histoire de gauche à droite.

Sa

... [tronqué pour la traduction]

Skills associés