Symboles SVG portables

Composez et partagez des symboles SVG statiques avec des liaisons Ganter sûres et des bornes de raccordement typées.

Afficher en Markdown

Les symboles Ganter tiennent le dessin et les données vivantes séparés. Le dessin est du SVG ordinaire et statique. Ganter Lab possède chaque correspondance de valeur et chaque animation : un fichier importé ne peut donc exécuter ni script, ni gestionnaire d'événement, ni code d'animation embarqué, ni requête réseau. Cette page est la référence complète du modèle de création : ce qu'un symbole déclare, ce que l'import accepte et refuse, et comment les symboles voyagent d'une station à l'autre.

Un symbole déclare trois choses par-dessus son dessin :

  • Zones actives : des entrées nommées (remplissage, contour, mouvement, texte, visibilité) qu'une instance posée sur un tableau de bord alimente ensuite depuis une adresse Logic ou une valeur fixe.
  • Bornes : des points de raccordement typés sur le périmètre, pour que le tableau de bord puisse acheminer tuyaux, gaines, câbles et arbres entre symboles.
  • Suggestions : des compositions facultatives avec d'autres symboles, posées explicitement.

Symboles système et Mes symboles

Le catalogue a deux origines, filtrables partout où des symboles sont listés :

Origine Référence Ce que c'est
Système system:<clé-stable> Les bibliothèques intégrées livrées avec l'application. Inspectables et exportables, jamais modifiables sur place.
Les miens user:<guid> Les symboles que vous avez créés, importés ou dupliqués. Modifiables et supprimables.

Chaque symbole système propose Dupliquer dans Mes symboles : la copie est une ressource utilisateur figée et possédée à part (dessin, zone d'affichage, ajustement, encombrement, zones actives, configurations de type, bornes et suggestions copiés ensemble), elle continue donc de se comporter comme au moment du choix, même quand une mise à jour ultérieure change l'original. Supprimer un symbole utilisateur demande une confirmation ; les tableaux de bord qui le référencent encore affichent un espace réservé au lieu de se casser.

Les façons de créer un symbole

  • Importer un fichier : Logic > Ressources > Symboles > Importer un symbole accepte un .svg simple ou un paquet .ganter-symbol.json complet. Chaque import crée une nouvelle ressource avec sa propre identité ; il n'écrase jamais un symbole existant, et une collision de nom se résout par un suffixe (« 2 », « 3 », etc.) plutôt que par un échec. Le sélecteur refuse les fichiers de plus de 1 MB avant même de lire un octet. Après l'import d'un SVG simple, l'application indique combien d'éléments dangereux elle a retirés, s'il y en avait.
  • Composer dans l'application : Nouveau symbole utilisateur ouvre un éditeur pour le nom, le balisage SVG, la disposition sur le tableau de bord (ajustement et encombrement initial) et les zones actives ; une fois le symbole créé, les changements valides sont enregistrés automatiquement. La géométrie des bornes n'est volontairement pas modifiable dans l'application : des bornes typées ne peuvent venir que d'un paquet, et les bornes définies par un paquet sont conservées en lecture seule à travers les modifications ultérieures.
  • Demander à une IA : deux chemins partagent exactement le même contrat. Par le point de terminaison MCP intégré, l'outil symbol_validate simule l'import et symbol_import enregistre une nouvelle ressource ; tous deux portent le contrat complet dans leur description. Depuis une conversation externe sans accès à l'application, Copier l'instruction de conversation, dans le volet Symboles, copie une consigne autoportante ; enregistrez le SVG ou le paquet renvoyé comme fichier et importez-le ici.

Voir Logic pour l'espace de travail des ressources qui l'entoure.

Préparer un SVG simple

Donnez un id SVG stable à chaque partie que vous voulez lier. Après l'import, ces identifiants apparaissent dans les sélecteurs de cible des zones actives. Les identifiants et les noms de zone active partagent une grammaire : ils commencent par une lettre ou _, continuent par des lettres, des chiffres, _, ., : ou -, et comptent 128 caractères au plus.

Les attributs facultatifs data-ganter-* sont le seul balisage propre à Ganter qu'un symbole peut porter :

Attribut Sur Ce qu'il déclare
data-ganter-pivot="x y" tout élément liable Le point de pivot exact (en coordonnées de la zone d'affichage) pour les zones actives de rotation, d'échelle et de rotation continue. Obligatoire sur l'élément visé par ces trois natures.
data-ganter-spin-ratio un enfant d'un élément en rotation continue La vitesse relative d'un rotor enfant visible. Finie, non nulle, d'une valeur absolue de 100 au plus ; une valeur négative tourne dans l'autre sens. Retiré si l'élément ne déclare pas aussi son propre pivot.
data-ganter-role tout élément Un rôle sémantique stable pour les outils de création. Purement informatif.
data-ganter-fit-width <text> / <tspan> Affichage borné, sur demande, pour une zone active de texte : quand le texte lié mesure plus que ce nombre d'unités de la zone d'affichage, la police rétrécit pour tenir.
data-ganter-fit-min-font-size <text> / <tspan> La plus petite taille de police jusqu'à laquelle l'ajustement peut rétrécir. En deçà, l'élément affiche le texte de repli tandis que la valeur entière reste dans le nom accessible et dans l'infobulle.
data-ganter-fit-fallback <text> / <tspan> Le texte affiché quand même la taille de police minimale ne permet pas d'afficher la valeur.

Les bornes de raccordement ne vivent pas dans le SVG et ne visent pas des identifiants d'élément SVG. Les attributs nommés data-ganter-port ou data-ganter-port-* ne font pas partie du format : un import de SVG simple les retire ; un paquet strict qui en contient est rejeté.

L'import d'un SVG simple donne toujours un symbole purement visuel valide : zéro borne, zéro zone active. L'inspecteur signale qu'aucune borne raccordable n'existe, parce que le rôle, le type, la direction extérieure et le chemin interne n'ont pas été déclarés. Ganter ne déduit pas ces champs du nom de fichier, de la catégorie ni du dessin, et n'ouvre aucun éditeur interne de bornes ni de chemins.

Ce que l'assainissement accepte

La même politique SVG s'applique à tous les chemins d'entrée (import de fichier, éditeur intégré, MCP, paquet). Elle est délibérément plus étroite que SVG :

  • Gardé : la géométrie et la structure inertes, soit svg, g, defs, symbol, use, path, rect, circle, ellipse, line, polyline, polygon, text, tspan, title, desc, clipPath, mask, linearGradient, radialGradient, stop, pattern, marker, avec les attributs de présentation (remplissage, contour, opacité, transformation, style) et les libellés ARIA.
  • Retiré ou refusé : <script>, <style>, <foreignObject>, les gestionnaires d'événements, l'animation embarquée, et toute URL externe ou en data:/file:/http(s). Seules les références internes url(#id) et href="#id" survivent.
  • Limites : le balisage compte 512 KB et 4096 éléments au plus.

Les peintures sûres sont les couleurs hexadécimales, les couleurs nommées de CSS, rgb()/rgba()/hsl()/hsla(), et les jetons de thème de l'application var(--color-<nom>) (par exemple var(--color-success), var(--color-symbol-off)). Les jetons de thème sont ce qui permet à un seul dessin de s'adapter au clair et au sombre : livrez un dessin qui référence des jetons, jamais deux variantes de thème.

Le traitement d'une violation dépend du chemin d'entrée : un SVG simple est réparé (les éléments dangereux sont retirés et chaque retrait est signalé par un avertissement) ; un paquet est strict et se voit rejeté, les premières violations nommées, au lieu d'être réparé en silence.

Paquet portable v2

Exporter un symbole crée un fichier .ganter-symbol.json. Chaque champ de l'enveloppe est obligatoire ; les trois tableaux du contrat peuvent être vides mais doivent être présents :

Champ Exigence
$schema Exactement https://ganterlab.com/schemas/ganter-symbol-v2.schema.json.
format Exactement ganter-symbol.
version Exactement 2. Les paquets en version 1 sont rejetés au lieu de passer par un lecteur d'ancien format.
name Le nom affiché. Un import peut le remplacer, et une collision reçoit automatiquement un suffixe.
svg Du SVG statique assaini, dont l'élément racine porte un viewBox égal au champ viewBox.
viewBox minX minY width height : quatre nombres finis, largeur et hauteur positives.
fit contain, stretch, stretch-x ou stretch-y.
footprint { "width": 1..24, "height": 1..12 }, les cellules conseillées sur le tableau de bord.
slots Tableau des déclarations de zone active (ci-dessous).
typeConfigurations Tableau des choix de type partagés entre bornes (ci-dessous).
terminals Tableau de 16 bornes complètes au plus (ci-dessous).
suggestions Tableau des compositions ordonnées (ci-dessous).

Le schéma JSON public Ganter symbol v2 valide l'enveloppe de transport. L'importeur effectue ensuite les contrôles sémantiques que JSON Schema ne peut pas exprimer : l'existence des cibles SVG, la géométrie des chemins internes, la compatibilité des suggestions. Un paquet est strict dans toutes les dimensions : le balisage dangereux, les champs inconnus, les entrées nulles dans un tableau et les anciens contrats ports[], anchors[], profile et connectionStyle sont rejetés au lieu d'être réparés.

Le paquet ne contient jamais d'adresse de station, de liaison de tableau de bord, de choix de type par instance, de GUID de base de données ni d'identité d'utilisateur. Une zone active qui porte une adresse Logic ne peut même pas être exportée : l'adresse appartient à l'instance posée, pas au symbole réutilisable.

Taille, zone d'affichage et ajustement

La zone d'affichage (viewBox) est l'espace de coordonnées naturel du symbole. Les bornes et les chemins internes y sont déclarés, et elle doit correspondre exactement au viewBox de la racine du SVG ; un paquet dont les deux zones d'affichage divergent est rejeté. Les zones d'affichage non carrées sont pleinement prises en charge : un long convoyeur n'a donc pas à tenir dans un carré.

Le mode d'ajustement dit comment le dessin occupe le rectangle que l'opérateur dessine sur le tableau de bord :

Ajustement Comportement
contain Conserve les proportions ; le dessin s'insère avec des marges dans le rectangle de la cellule. C'est la valeur par défaut.
stretch Remplit le rectangle sur les deux axes, quitte à déformer.
stretch-x Étire horizontalement, garde la proportion verticale naturelle.
stretch-y Étire verticalement, garde la proportion horizontale naturelle.

L'encombrement est la taille initiale, en cellules de la grille du tableau de bord, au moment où le symbole est posé pour la première fois : largeur de 1 à 24, hauteur de 1 à 12 (l'éditeur propose 4 × 4 par défaut). C'est une suggestion, pas une contrainte ; l'opérateur redimensionne librement ensuite.

Deux barrières distinctes bornent la taille d'un import : le sélecteur de fichier refuse tout ce qui dépasse 1 MB avant de le lire, et l'assainissement refuse un balisage de plus de 512 KB ou de plus de 4096 éléments.

Zones actives : la surface de liaison

Une zone active déclare une entrée : quel élément elle pilote, ce qu'elle lui fait, et comment les valeurs d'entrée se transforment en sortie. L'instance posée sur un tableau de bord choisit ensuite la source de chaque zone active (une adresse Logic ou une valeur fixe) ; le symbole lui-même ne conserve jamais de source.

Chaque zone active porte :

Champ Signification
name Le nom de paramètre montré à l'auteur du tableau de bord. Grammaire d'identifiant ci-dessus ; unique parmi les zones actives du symbole.
elementId L'id d'un élément SVG existant. Un élément accepte au plus une zone active par canal : deux zones actives ne peuvent donc pas se disputer le remplissage du même élément.
kind L'une des treize natures ci-dessous.
inMin, inMax La plage d'entrée : les deux valeurs mises en correspondance avec outMin/outMax. Nombres finis ; utilisés par les natures continues et comme milieu de seuil par fill et stroke.
outMin, outMax La plage de sortie dans l'unité de la nature (degrés, unités de la zone d'affichage, 0..1, degrés par seconde). Nombres finis.
outMinSecondary, outMaxSecondary Second axe de sortie facultatif, pour translate et scale seulement : la sortie principale est X et la secondaire est Y. Fournissez les deux ou aucune.
onColor, offColor Peintures sûres pour fill et stroke (les deux états du seuil). Pour fillColor et strokeColor, onColor est la couleur d'aperçu de l'inspecteur.

Les treize natures de zone active :

Nature Ce qu'elle pilote Remarques
rotate Fait tourner l'élément ; l'entrée est mise en correspondance linéaire avec des degrés. La cible doit déclarer data-ganter-pivot.
opacity L'opacité de l'élément ; l'entrée est mise en correspondance avec 0..1.
fill Peint le remplissage avec offColor sous le milieu de la plage d'entrée et avec onColor à partir de ce milieu. Une entrée booléenne bascule directement. Vise les formes qui se remplissent (pas <line>).
visible Affiche ou masque l'élément selon la véracité de la valeur.
text Remplace le contenu textuel de l'élément par la valeur mise en forme. Vise <text> et <tspan> seulement ; à combiner avec les attributs data-ganter-fit-* pour un affichage borné.
translate Déplace l'élément en unités de la zone d'affichage ; la sortie principale est X, la secondaire facultative est Y.
scale Met l'élément à l'échelle ; la sortie principale est X, la secondaire est Y (omise = échelle uniforme). La cible doit déclarer data-ganter-pivot.
stroke Peint le contour selon la même règle de seuil que fill.
spin Rotation continue dans le temps ; l'entrée est mise en correspondance avec une vitesse angulaire en degrés par seconde. Les enfants portant data-ganter-spin-ratio tournent avec lui au rapport déclaré. La cible doit déclarer data-ganter-pivot. Le mouvement est cadencé par l'hôte et indépendant des préférences d'animation du système d'exploitation.
spinEnabled Met en pause ou reprend la zone active spin du même élément sans le masquer. Exige une zone active spin visant le même élément.
fillColor Règle le remplissage directement depuis la valeur de couleur liée (une ressource Couleur, une variable Couleur ou une couleur CSS sûre).
strokeColor Règle le contour directement depuis la valeur de couleur liée.
strokeWidth Règle la largeur du contour directement, en unités utilisateur SVG de 0.5 à 32 ; ni suffixe d'unité, ni CSS. Une entrée invalide, non résolue ou de mauvaise qualité rétablit le stroke-width d'origine ; la réinitialisation, le remontage et la destruction aussi.

Ces zones actives habillent le dessin ; elles n'habillent jamais les cheminements de raccordement du tableau de bord, dont la couleur et la largeur sont globales par type de tracé.

À qui appartient la liaison

Le symbole déclare des paramètres et des choix de type permis, non des sources vivantes ni la sélection d'une instance. Après avoir posé un composant Symbol, l'opérateur associe chaque zone active à une adresse Logic ou à une valeur fixe, et choisit chaque type de tracé configurable sur cette instance. Ces choix restent dans la station et ne sont jamais exportés avec le symbole réutilisable. Une zone active non associée reste neutre : l'élément garde l'apparence qui lui a été donnée.

Positions globales et types de tracé

Chaque borne référence une position du catalogue fixe de seize ancrages du périmètre. Un paquet ne conserve que l'anchorId ; il ne répète et ne remplace jamais des coordonnées. Les positions, en fractions normalisées de la zone d'affichage :

  • en haut : top-left (0, 0), top-25 (0.25, 0), top-50 (0.5, 0), top-75 (0.75, 0), top-right (1, 0) ;
  • à droite : right-25 (1, 0.25), right-50 (1, 0.5), right-75 (1, 0.75) ;
  • en bas, dans le sens horaire : bottom-right (1, 1), bottom-75 (0.75, 1), bottom-50 (0.5, 1), bottom-25 (0.25, 1), bottom-left (0, 1) ;
  • à gauche, toujours dans le sens horaire : left-75 (0, 0.75), left-50 (0, 0.5), left-25 (0, 0.25).

Ce sont des positions de périmètre, pas une grille 5 × 5. Un symbole ne peut ni ajouter une autre position, ni conserver ses propres coordonnées d'ancrage.

Les huit types de tracé globaux sont liquid, gas, air-duct, electrical, signal, network, material et mechanical-shaft. Utilisez Logic > Ressources > Types de tracé pour configurer la couleur et l'épaisseur de trait associées à chaque type. Les symboles et les tracés conservent l'identifiant stable du type : un changement global restyle donc chaque cheminement qui l'utilise. Un paquet ne copie jamais la couleur ni la largeur, et n'a pas de variantes de cheminement petites, standard ou grandes.

Deux extrémités forment un tracé défini quand elles se résolvent vers le même type. Le rôle de la borne aide à la création et à la relecture, mais n'interdit pas à lui seul un arrangement de réseau.

Choix de type partagés

Un symbole qui peut travailler avec plus d'un fluide déclare une configuration de type partagée plutôt que de dupliquer son dessin :

{
  "id": "process-type",
  "name": "Process type",
  "allowedTypes": ["liquid", "gas"],
  "defaultType": "liquid"
}

L'id est une clé stable : des lettres minuscules et des chiffres séparés par des tirets simples, commençant et finissant par un caractère alphanumérique (les majuscules sont refusées). allowedTypes n'est pas vide et contient des identifiants de type globaux uniques ; defaultType doit lui appartenir ; name est obligatoire. Chaque borne qui référence process-type suit un choix unique fait sur l'instance posée sur le tableau de bord. Une définition peut porter plusieurs configurations indépendantes, par exemple le fluide de procédé et le fluide d'évent, pendant que d'autres bornes restent fixes.

Bornes complètes

Chaque borne raccordable déclare une position globale, un rôle, exactement un type fixe ou une configuration partagée, une direction vers l'extérieur dans l'orientation d'origine, et un chemin d'arrivée interne :

{
  "anchorId": "left-50",
  "role": "input",
  "typeConfiguration": "process-type",
  "direction": "west",
  "internalPath": [
    { "x": 18, "y": 50 },
    { "x": 36, "y": 50 },
    { "x": 48, "y": 62 }
  ]
}

Les règles, toutes vérifiées à l'import :

  • 16 bornes au plus, et chaque identifiant d'ancrage utilisé une seule fois.
  • role vaut input, output ou bidirectional ; direction vaut north, east, south ou west.
  • Exactement l'un de type (un type de tracé global) ou de typeConfiguration (l'identifiant d'une configuration déclarée) : jamais les deux, jamais aucun.
  • L'ancrage global converti dans la zone d'affichage naturelle du SVG est le départ implicite de internalPath ; ne le répétez pas comme premier point. Les coordonnées sont des valeurs absolues de la zone d'affichage, non des fractions normalisées, et le chemin compte au moins un point.
  • Chaque segment reste à l'intérieur de la zone d'affichage, a une longueur non nulle, et est horizontal, vertical ou exactement à 45° ; deux segments consécutifs tournent de 90° au plus.
  • Les bornes exigent que le SVG porte une zone d'affichage.

Le tableau de bord dessine le chemin interne sous le dessin de l'équipement, le transforme lors d'un redimensionnement, d'un quart de tour et des symétries, et conserve la largeur visuelle du type de tracé global au lieu de la mettre à l'échelle avec le symbole : un seul trait continu court donc de l'intérieur d'un corps à l'intérieur de l'autre.

Une borne est tout ou rien. Un paquet strict comportant une borne partielle est invalide ; un paquet purement visuel utilise plutôt un tableau terminals vide. Rien n'est jamais déduit pour combler un trou.

Suggestions ordonnées

Une suggestion enregistre une composition intentionnelle, pose exacte de la cible comprise :

{
  "sourceAnchorId": "right-75",
  "targetSymbol": "system:capping-station",
  "targetAnchorId": "left-75",
  "targetRotationDegrees": 0,
  "targetFlipHorizontal": false,
  "targetFlipVertical": false,
  "connectionType": "material"
}

Validation : sourceAnchorId doit être l'une des bornes de ce symbole ; targetSymbol doit être une référence qualifiée par son origine, et dans un paquet portable elle ne peut être que system:<clé-stable> (un GUID d'utilisateur n'a de sens que dans la station qui le possède) nommant un symbole présent dans le catalogue système avec une borne à targetAnchorId ; la rotation vaut 0, 90, 180 ou 270 et les deux indicateurs de symétrie sont obligatoires ; chaque suggestion doit être unique. connectionType ne peut être omis que si les types fixes égaux des deux extrémités lèvent l'ambiguïté ; il est obligatoire dès qu'une extrémité est configurable, et il doit alors être permis des deux côtés.

Les suggestions sont orientées et l'ordre du tableau fixe la priorité, mais elles ne sont jamais une liste d'autorisation pour les tracés ordinaires du tableau de bord. Avec un tableau suggestions vide, l'inspecteur signale qu'aucune composition suggérée n'existe, au lieu d'inventer un partenaire de catalogue.

Ce que l'import refuse

Une liste rapide des refus, pour qu'un import raté se lise au lieu de se deviner. Pour un SVG simple, seul le premier groupe s'applique, et à l'intérieur de celui-ci seules les limites de taille, un XML mal formé et une racine <svg> absente font refuser l'import : le balisage interdit est réparé avec un avertissement. Pour un paquet, tout ce qui suit est un rejet ferme.

Dessin

  • Un fichier de plus de 1 MB, un balisage de plus de 512 KB, ou plus de 4096 éléments.
  • Un XML mal formé, ou une racine qui n'est pas un <svg> assaini.
  • Dans un paquet : tout balisage que la liste d'autorisation aurait dû retirer (scripts, gestionnaires d'événements, références externes, éléments ou attributs interdits).
  • Un viewBox qui n'est pas quatre nombres finis avec une largeur et une hauteur positives, ou qui diffère de celui de la racine du SVG ; un paquet sans aucune zone d'affichage à la racine.

Enveloppe

  • Un schéma, un format ou une version autres que ceux du contrat v2 ; des champs inconnus n'importe où ; un name, un fit, un footprint ou l'un des trois tableaux manquants ; une entrée nulle dans un tableau.
  • Un fit hors des quatre modes ; un encombrement hors de 1 à 24 par 1 à 12.

Zones actives

  • Un nom ou un identifiant d'élément hors de la grammaire d'identifiant ; un nom de zone active en double ; un identifiant de cible que le SVG ne contient pas ; une nature que l'élément visé ne peut pas prendre (du texte sur un élément qui n'est pas du texte, un remplissage sur un <line>).
  • Une zone active rotate, spin ou scale dont la cible n'a pas de data-ganter-pivot fini ; une zone active spinEnabled sans zone active spin sur le même élément.
  • Deux zones actives sur le même canal d'un même élément. Chaque nature est son propre canal, sauf que fill et fillColor partagent le canal du remplissage et que stroke et strokeColor partagent celui du contour : un élément ne peut pas plus prendre deux rotations que deux remplissages.
  • Des nombres de plage non finis ; une sortie secondaire n'ayant qu'une seule borne, ou portée par une nature autre que translate et scale ; une peinture dangereuse ; une zone active qui porte une adresse Logic.

Raccordements

  • Plus de 16 bornes ; un identifiant d'ancrage répété ou inconnu ; une borne portant à la fois ou ni l'un ni l'autre de type et typeConfiguration ; un identifiant de type ou de configuration inconnu ; un chemin interne invalide (hors de la zone d'affichage, segments de longueur nulle ou d'angle interdit, virage de plus de 90°).
  • Une configuration de type dont l'identifiant est invalide, dont le nom manque, dont les types permis sont en double ou inconnus, ou dont la valeur par défaut est hors de sa propre liste.
  • Une suggestion dont la borne source n'existe pas, dont la cible n'est pas un symbole système portant la borne nommée, dont la pose n'est pas un quart de tour, ou dont le type de tracé n'est pas accepté des deux côtés.

symbol_validate, sur le point de terminaison MCP, exécute exactement cet import comme une simulation et signale chaque erreur, avertissement et remarque sans rien enregistrer.

Empaqueter et partager

Exporter le paquet (disponible aussi bien pour les symboles système que pour les vôtres) télécharge <nom>.ganter-symbol.json avec le dessin assaini et le contrat complet : $schema, format, version, name, svg, viewBox, fit, footprint, slots[], typeConfigurations[], terminals[] et suggestions[], les trois tableaux de raccordement présents même quand ils sont vides. Ce qui ne voyage jamais : les adresses de station, les choix de type par instance, l'identité en base de données, l'identité de l'utilisateur, et les couleurs et largeurs de type de tracé de la station.

Sur la station qui reçoit, le même fichier passe par Importer un symbole (ou par symbol_import sur MCP) et arrive comme un nouveau symbole utilisateur, bornes comprises. Comme l'identité d'un type est un identifiant stable et que l'apparence est globale, les cheminements d'un symbole importé suivent immédiatement le style des types de tracé de la station qui le reçoit.