# 图元

> 图元素材库：十一个系统图元库和“我的图元”、图库的搜索与筛选、带实时输入和连接点的检视面板、新建用户图元编辑器和每一种可绑定区域、导入图元…、导出图元包、复制、复制对话指令，以及一个图元用在哪里。

**Symbols** 是 Assets 根下面的第四个类别：仪表画面上的[图元](component-symbol)组件所画、所驱动的那些图形。面板标题是“图元”，配一行“为现代仪表画面、试验台、联网产品、标准图示、工业系统和厂房量身打造的图元库。每一个系统图元都可以查看，也可以复制到‘我的图元’。”，还有一枚数量胶囊。读取和查看需要**查看 Logic**；创建、导入、复制、编辑和删除需要**配置 Logic**。一个图元传输时用的那种文件格式，写在[可移植 SVG 图元](ganter-symbols)上。

## 那些图元库 {#the-libraries}

| 图元库 | 它装的是什么 | 标准 | 图元数 |
| --- | --- | --- | --- |
| Process | 面向监控仪表画面和工艺流程图的分层工艺设备图形 | | 86 |
| ISA / P&ID | 示意性的工艺、管道、阀门和仪表图形 | ANSI/ISA-5.1 / ISO 10628 | 99 |
| Manufacturing & Material Flow | 离散制造、装配、批次、包装、检验和厂内物流设备 | | 48 |
| Lab & Test Bench | 实验室、数据采集、计量、被测件工装、环境试验台和质量检验图元 | | 35 |
| Prototyping Electronics | 控制器、开发板、连接器、传感器模块、执行器、电源和无线 | | 35 |
| IoT Field Sensors | 环境、状态、位置、计量、无线网关和边缘控制图元 | | 36 |
| Smart Home & Building | 照明、舒适、门禁、安防、家电、给水以及可互操作的控制设备 | Matter / BACnet / 常用楼宇自动化画法 | 39 |
| IT, Network & Datacenter | 计算、机柜、存储、网络、安全、云平台、机房供电和制冷 | 常用 IT 基础设施 / SNMP / Redfish 画法 | 35 |
| Electrical & Energy | 单线图、配电、变换、计量和可再生能源，触点状态由几何形状表示 | IEC 60617 / IEEE 315 | 39 |
| Energy, Microgrid & e-Mobility | 分布式发电、变换、储能、计量、保护、微电网和电动汽车充电 | 面向 IEC / IEEE / OCPP 的仪表画面画法 | 40 |
| Facilities & Utilities | 暖通空调、给水和污水、安全系统、厂区公用工程和控制基础设施 | | 38 |
| 我的图元 | 你自己拼出来、导入进来或者复制出来的那些图元 | | 你的 |

那些系统图元库是 Ganter Lab 的原创图形，编译进产品并且只读：一次更新会把它们整个换掉，而不碰你工作站上的数据。每一份定义都带着一个稳定的引用 `system:<key>`，它所属的图元库和类别、一段说明、搜索标签、它适用的标准，以及出处和许可元数据。

## 图库 {#the-gallery}

卡片上方是：**搜索**（占位提示“名称、类别或关键词”；它不分大小写地匹配图元的名称、说明、类别、标准和标签；图元库用它自己的筛选项来挑），**素材库**（“全部库（530）”，或者某一个库配上它的数量；挑定一个库会清掉类别，并在筛选项下面显示这个库的说明），**类别**（“全部类别”，或者所挑那个库的某一个类别），**来源**和**每页**。一张卡片显示它所属的图元库、一张按图形自然比例画的预览、名称、类别、来源（系统或者我的），以及一行能力说明：“静态”“1 个输入”或者“N 个输入”，图元声明了连接点时后面再跟“· N 个连接点”。结果为空时说“没有符合这些筛选条件的图元。”，并给出**清除筛选**。你自己的图元读不出来时，会有一行提示说“‘我的图元’暂时不可用。这里只列出系统图元库。”，而不是把系统那一包当成整个目录端上来。

## 检视面板 {#the-inspector}

选中一张卡片会在图库旁边打开检视面板：

- 名称，加一枚标记：**系统 · 只读**、**我的图元**，或者仅在图元是新建且尚未创建，或打开的编辑带有会阻止自动保存的错误时才显示的**未保存的草稿**（编辑由系统自动保存时，包括保存前的半秒，标记仍是**我的图元**）。
- 它所属的图元库、类别和标准；那段说明。
- **占位尺寸**（建议的仪表画面尺寸，以格数计，宽 × 高）和**适配**（包含、双向拉伸、横向拉伸或者纵向拉伸）。
- “N 个输入 · N 个连接点”，没有连接点时是“仅视觉”。
- **图形出处**，一个可展开的段落，写着出处，系统图元还写着许可。
- 那些命令：每个角色都能用的**导出图元包**；系统图元有**复制到“我的图元”**，你的图元有**编辑**和**删除**（只对能配置的角色）。
- 预览台：净化之后的图形，由和仪表画面同一个运行时画出来，并在每一个连接点的锚点上画一个手柄。画不出来的图形会让预览台留空，写着“无法预览”和原因。净化器不得不修补标记时，一个可展开的“预览使用净化后的 SVG”会列出那些修复（最多八条，然后是“还有 N 处修复没有列出。”）。
- **输入**：“这些临时常量只影响本次预览。”和**重置输入**。每一个已声明的可绑定区域各占一节，写着它的名称、它驱动的效果、一句描述这层映射的话、输入范围和目标元素（`#id`），外加一个可以试一试的控件：一个数字（输入范围有限时配一个滑块）、一个开关、一个文本框，或者一个取色器配一个上色值输入框。一个都没有时写“这个图元没有声明任何动态输入。”；声明本身不合法时，显示它的错误而不是控件。你在这里设的那些常量绝不会被保存，也绝不会传到仪表画面上。

那些效果，以及检视面板怎样描述它们：

| 种类（编辑器里的标签） | 效果 | 控件 | 说明 |
| --- | --- | --- | --- |
| Rotate | 旋转角度 | 数字 | 从 `<output min>`° 旋转到 `<output max>`° |
| Opacity | 不透明度 | 数字 | 把不透明度从 `<output min>` 变到 `<output max>` |
| Fill | 填充状态 | 开关 | 把填充从关状态颜色切换到开状态颜色；数值型信号源在输入区间的中点切换 |
| Visible | 可见性 | 开关 | 关时隐藏元素，开时显示它 |
| Text | 显示的文字 | 文本 | 替换元素内显示的文字 |
| Translate | 位置 | 数字 | 从 (x, y) 移动到 (x, y) 个 SVG 单位 |
| Scale | 缩放 | 数字 | 从 (x, y) 缩放到 (x, y) |
| Stroke | 描边状态 | 开关 | 把描边在关状态颜色和开状态颜色之间切换；数值型信号源在中点切换 |
| Spin (°/s) | 旋转速度 | 数字 | 以 `<min>`°/秒 到 `<max>`°/秒 的速度持续旋转；零表示暂停，负值表示反向 |
| Spin enabled | 旋转状态 | 开关，默认开 | 暂停或恢复旋转，既不隐藏元素，也不重置它的角度 |
| Fill color | 填充颜色 | 颜色 | 直接用颜色素材、颜色变量或字面预览颜色设置填充 |
| Stroke color | 描边颜色 | 颜色 | 直接用颜色素材、颜色变量或字面预览颜色设置描边 |
| Stroke width | 描边宽度 | 数字 | 直接设置描边宽度，0.5 到 32 个 SVG 单位 |

## 新建用户图元 {#new-user-symbol}

Symbols 那一行上的命令会在图库那一栏里打开编辑器（“新建用户图元”：“用惰性的 SVG 组合图形，并声明它给仪表画面用的输入区域。”）；你打字的时候检视面板跟着这份未保存的草稿走，所以你在创建它之前就能把这个图元试一遍。

| 字段 | 它是什么 | 取值 / 默认值 | 效果 |
| --- | --- | --- | --- |
| 名称 | 显示名称。 | 必填；为空时提示“必须填写名称。”。 | 和图标或颜色不同，图元的名称以后还能改：仪表画面按 id 引用它。 |
| SVG 标记 | 图形，以文本粘贴进来。 | 必填。 | 边打字边净化；一个图形错误（“SVG 标记必须有一个 `<svg>` 根。”“SVG 标记超过了 512 KB 的上限。”，一个重复的 id……）会挡住创建，也挡住每一个可绑定区域。 |
| 适配 | 图形怎样填满仪表画面上的那个格子。 | 包含（默认）、双向拉伸、横向拉伸、纵向拉伸。 | 图元被放置时由仪表画面编辑器读取。 |
| 初始宽度、初始高度 | 一个新的仪表画面实例一开始占的格数。 | 1 到 24 格、1 到 12 格；默认 4 × 4。 | 同上。 |
| 连接点 | 一条只读的说明。 | “这份图形只有视觉部分。带类型的连接点可以由 Ganter Symbol v2 包提供。”，或者“保留了 N 个由图元包定义的连接点。连接点的几何位置在 Ganter Lab 里有意设为只读。”。 | 连接点不能在这里画、也不能在这里改：它们来自导入的图元包，或者来自复制出来的系统图元，而编辑时它们原样保留。 |
| 可绑定区域 | 这个图元对外暴露的那些输入（“每个可绑定区域对准一个 SVG 元素 id，并暴露一个安全的运行时基本操作。”）。 | **添加可绑定区域**会用一个自动生成的名字（先是 `param`，然后加编号）追加一行。 | 每一行有：一个名称、一个元素 id（一个下拉框列出标记里找到的那些 id，你也可以自己输入任意 id）、**移除可绑定区域**、种类、输入最小值和最大值、输出最小值和最大值（对 Translate 和 Scale 来说是 X 轴）、一对可选的 Y 最小值和最大值，以及按种类而定的东西：Stroke width 那一种带着说明“仪表画面传来的值就是 SVG 宽度，范围从 0.5 到 32。”；Fill color 和 Stroke color 带着一个预览颜色；其余每一种都带着一个开状态颜色和一个关状态颜色。 |

可绑定区域的规则，逐条报在字段下面，并把出问题的那一行描上边框：名称必须是一个标识符（首字符是字母或者 `_`，后面是字母、数字、`_`、`.`、`:` 或者 `-`）并且不重名；元素 id 必须在标记里存在；Text 只能对准 `text` 和 `tspan`；Fill 和 Fill color 对准可以填充的形状、组、`use` 和文字；其余各种对准组、`use`、形状和文字；Rotate、Spin 和 Scale 要求目标元素带着 `data-ganter-pivot="x y"`；每一个范围值都必须是有限数；Y 那一对要么都给要么都不给，并且只用于 Translate 和 Scale；开状态和关状态颜色必须是十六进制值、一个主题变量（例如 `var(--color-success)`）或者一个 CSS 颜色名；同一个元素在每个通道上最多接一个可绑定区域（填充、描边、描边宽度，其余每一种各一个）；一个 Spin enabled 区域要求同一个元素上有一个 Spin 区域。

只要还有错误没消，**创建图元**就一直置灰；**取消**或者**返回**会不创建就离开。成功之后操作记录条说“图元已创建。”，新卡片被选中。

## 编辑、复制、删除 {#edit-duplicate-delete}

**编辑**（只对你自己的图元）打开同一个编辑器，写着“名称、SVG 和可绑定区域的有效更改会自动保存。”：一次合法的更改会在最后一次编辑之后半秒保存（“图元已保存。”），而不合法的草稿不保存，并取消任何待执行的保存，所以存下来的图元绝不会和检视面板显示的东西不一致。**复制到“我的图元”**（针对系统图元）把图形、视图框、适配、占位尺寸、类型配置、连接点和建议一起复制进一个独立的图元，名字叫 `<Name>` copy（名字被占时依次是 `<Name>` copy 2……），并在图库里选中它，而不打开编辑器（“系统图元已复制到‘我的图元’。”）：检视面板在图库旁边显示它，凡是会把这份副本藏起来的搜索或筛选都会被清掉，图库翻到装着它的那一页，用**编辑**才打开它来编辑。系统定义本身绝不会被改动。**删除**会问“要删除‘X’吗？使用它的仪表画面会显示一个占位图形。 此操作无法撤销。”（“图元已删除。”）。

## 导入图元… {#import-symbol}

这一行上的第二个命令是一个文件选择器，接受最大 1 MB 的 `.svg` 和 `.ganter-symbol.json` 文件（“该图元文件超过了 1 MB 的上限。”）。内容决定走哪条路：

- **裸 SVG**（内容以 `<` 开头）作为只有视觉部分的图形导入：没有可绑定区域，也没有连接点。净化器修补它，操作记录条数出修复了多少处（“图元已作为新素材导入；移除了 3 处不安全的 SVG 内容。”）。名称是文件去掉扩展名之后的名字。
- **一个 Ganter symbol v2 包**（内容以 `{` 开头）整个导入：名称、SVG、视图框、适配、占位尺寸、可绑定区域、类型配置、连接点和建议。包是严格的：格式、版本和 schema 必须对得上，SVG 必须已经净化过（需要修补的包会被拒绝，而不是替它修补），视图框必须和 SVG 根一致，每一个连接点、配置和建议都必须合法（[那份约定](ganter-symbols)）。操作记录条点名第一个问题（“图元导入失败：…”）。

已经被你某个图元占用的名称会加后缀（“ 2”“ 3”……）。每一次导入都造一个新图元，绝不覆盖已有的。

## 导出图元包 {#export-package}

检视面板里的**导出图元包**把选中的那个图元（系统的和你自己的都行）下载成 `<name>.ganter-symbol.json`：就是导入所读的那种 v2 包，不带任何工作站身份，所以它可以在工作站之间流转（“已导出 `<file>`。”）。图形没有根视图框的图元，或者某个可绑定区域带着工作站地址的图元，会被拒绝（“图元导出失败：…”）。

## 复制对话指令 {#copy-chat-instruction}

**复制对话指令**会把一段自成一体的指令复制到剪贴板，交给一个够不着工作站的外部 AI 对话用。它开头是“Create a Ganter Lab symbol for me. Return ONLY the file content, either raw SVG or a single .ganter-symbol.json v2 package, with no commentary, so I can save it as a file and import it unchanged.”，接着是完整的 v2 约定（两种被接受的输入、包的外壳、十六个全局位置、八种连线类型、可绑定区域的种类和规则、主题变量、连接点的几何规则、净化器的上限，以及一个最小的合法包），最后讲怎么把答案带回来：把回复存成一个 `.svg` 或者 `.ganter-symbol.json` 文件，再在这里导入。代理的 `symbol_validate` 和 `symbol_import` 工具读的是同一份约定，所以一次对话和一个代理产出的是同一种文件。操作记录条说“对话指令已复制。把它粘贴到任意 AI 对话里，再把返回的 SVG 导入进来。”（或者“剪贴板拒绝了这次复制。”）。这个命令对每个角色都画出来，因为它只读不写。

## 一个图元用在哪里 {#where-a-symbol-is-used}

仪表画面上的[图元](component-symbol)组件按 `system:<key>` 或者 `user:<id>` 引用一个图元，把每一个可绑定区域映射到一个 Logic 地址，为任何一个可配置的连接点挑定连线类型，并用画在[仪表画面编辑器](view-editor)里的连线把连接点接起来，走的是那些[连线类型](assets-connection-types)。图元自己没有 Logic 地址。

## 这个素材库不做的事 {#what-the-library-does-not-do}

它不画、也不移动连接点和内部路径，不就地编辑系统图形，不导入需要修补的包，不保留版本历史，也不会自己在工作站之间共享你的图元：请导出再导入那个包。
