§10 · Интерактивный веб-экспорт

В отличие от остальных форматов (которые сериализуют один кадр), этот путь даёт живую, перетаскиваемую конструкцию в браузере: тяните свободные точки / глайдеры / слайдеры — зависимая геометрия пересчитывается прямо на странице. Под капотом — JSXGraph (его рендерер — SVG), а AnimaGeo транспилирует граф конструкции, а не картинку. Это единственный экспорт, который не может выдать ни один «скриншот-из-GeoGebra» инструмент — он требует семантического графа, которым AnimaGeo уже владеет.

Зачем

Цель — встраивать построения как управляемые подвижные чертежи в любой веб-проект (React / Vue / Svelte / vanilla / без сборки), с понятной системой сигналов и действий в терминах конструкции (имена элементов + AnimaGeo-типы), а не движка рендеринга. Слои:

СлойЧто
Python (библиотека)exportJSXGraph(output="spec") → animageo-board/v1 (декларативные данные) + JSON-схема
@animageo/runtimecreateBoard(spec, container, opts) → BoardHandle: сигналы + действия; JSXGraph инъектируется; без глобалей
<animageo-board>Web Component — сигналы как CustomEvent, действия как методы
адаптерытонкие шаблоны React / Vue / Svelte / vanilla (~30 строк)

Живой пример

Это настоящая JSXGraph-доска, построенная из спеки, которую выдал Python (exportJSXGraph(output="spec") на ex_general.ggb). Перетащите точки A, B, C или глайдер G — зависимая геометрия и состояние внизу обновляются live.

— состояние конструкции (сигнал change):

…
Если вы читаете гайд из файловой системы (file://), браузер заблокирует загрузку модулей/спеки. Запустите сервер гайда (PYTHONPATH=. python3.13 docs/guide/server/serve.py) и откройте страницу по http://127.0.0.1:8765/.

Экспорт: html / js / spec

scene.loadGGB("scene.ggb", style="style.json", px_size=[800, 600])

scene.exportJSXGraph("board.html")              # самодостаточная страница (по умолч.)
scene.exportJSXGraph("board.js",  output="js")  # фрагмент для встраивания
scene.exportJSXGraph("board.json", output="spec")  # декларативный animageo-board/v1
outputЧто этоКогда
"html"самодостаточная страница (CDN JSXGraph + MathJax)быстро показать / iframe
"js"фрагмент-скрипт initBoard + createвставить в готовую страницу
"spec"декларативный JSON (animageo-board/v1), без JS-строкинтеграция в приложение через рантайм
"json"legacy-спека (несёт JS-строки)обратная совместимость
"moodle"<jsxgraph>-блок для filter_jsxgraphMoodle

CLI: python -m animageo scene.ggb -o board.html (или -o board.json --format jsxgraph для спеки).

Контракт animageo-board/v1

Спека — это eval-free структурированные данные: консьюмеру не нужно исполнять JS, чтобы построить доску. JSON-схема поставляется в пакете (animageo/exporters/jsxgraph/board.schema.json, доступна через load_schema()) и реальные экспорты валидируются против неё в тестах.

{
  "format": "animageo-board/v1",
  "boundingbox": [-8, 6, 8, -6],
  "inputs": [
    { "name": "A", "kind": "point",  "x": -2, "y": -1 },
    { "name": "G", "kind": "glider", "on": "f", "t": 0.4, "x": 1.2, "y": 0.7 }
  ],
  "elements": [
    { "name": "M", "role": "live", "kind": "midpoint",
      "engine": "midpoint", "parents": [{"ref":"A"}, {"ref":"B"}], "attrs": {} },
    { "name": "f", "role": "static", "kind": "Function",
      "engine": "curve", "parents": [[/*xs*/],[/*ys*/]], "tracksDrag": false }
  ],
  "coverage": [ /* live vs static по каждому элементу */ ]
}

Формы parents[]: {"ref": name} · число · [x, y] · [[xs],[ys]] · {"fn": body} (живая функция-координата) · {"js": expr} (escape-hatch). Полная таблица ключей — §reference.

Рантайм: сигналы и действия

import { createBoard } from '@animageo/runtime';

const spec = await fetch('/board.json').then(r => r.json());
const board = createBoard(spec, document.getElementById('box'));

// сигналы наружу
board.on('ready',  () => console.log('built', board.getState()));
board.on('change', ({ name, value, state }) => updateApp(state)); // драг (непрерывно)
board.on('commit', ({ name, value }) => save(name, value));        // конец драга

// действия внутрь
board.setState({ A: { x: 1, y: 2 } });   // управляемый режим
СигналКогда
readyдоска построена (после typeset MathJax)
changeсвободная точка / слайдер / глайдер движется (непрерывно)
commitдраг завершён
viewchangepan / zoom
errorодин элемент не построился

Действия: getState/setState, getValue/setValue, getElement, reset, setVisible/setStyle, destroy. Словарь — в терминах конструкции (имена + AnimaGeo-типы), не JSXGraph. JSXGraph инъектируется как peer-зависимость; нет глобалей; несколько досок на странице независимы.

Web Component и адаптеры

Наименьший общий знаменатель для интеграции без фреймворка — <animageo-board>: сигналы → CustomEvent, действия → методы элемента.

<animageo-board id="b" spec="/board.json" debounce="50"
                style="display:block;width:640px;height:480px"></animageo-board>

<script type="module">
  import '@animageo/web-component';   // регистрирует <animageo-board>
  const el = document.getElementById('b');
  el.addEventListener('animageo:change', (e) => console.log(e.detail.state));
  // el.setState({ A: { x: 1, y: 2 } });
</script>

В каталоге web/adapters/ — тонкие шаблоны useAnimageoBoard() (React-хук), composable (Vue), action (Svelte) и vanilla. Это примеры, не ядро: каждый проект дописывает ~30 строк под свой стек.

Live vs static

Экспорт честно делит элементы на живые и замороженные и пишет coverage-отчёт (логируется на INFO: N live, M static).

Ограничения

Полный разбор архитектуры и контракта — docs/jsxgraph_web_integration_audit.md и docs/jsxgraph_web_integration_plan.md; код — каталог web/.