Для кого: интеграторы, которым нужно поднять рабочий canvas с редактором и библиотеками shapes.
Что получите: корректный порядок инициализации, React-обёртка, чеклист первого запуска.
Предварительные знания: Установка и подключение.
Эталон — src/renderer/src/hooks/useEngine.ts и src/renderer/src/App.tsx.
sequenceDiagram
participant Host
participant Canvas as EulergraphCanvas
participant Engine as EulerGraph
Host->>Canvas: mount container ref
Canvas->>Engine: new EulerGraph dom
Engine->>Host: emit started
Host->>Engine: addScene
Host->>Engine: setCurrentScene
Host->>Engine: onStart callback
Note over Host,Engine: enableServices уже вызван в onEngineSet
Host->>Engine: registerStandardLibs
Host->>Engine: Stencil.register external libs
Host->>Engine: Stencil.loadLibs
Host->>Engine: fitToWidth / render
Важно:
enableServices вызывается при получении экземпляра engine (onEngineSet), до или параллельно с started — см. App.addScene + setCurrentScene — в обработчике started (в useEngine), до onStart.registerStandardLibs и loadLibs — в onStart host-приложения.import { useCallback, useState } from "react"
import { EulerGraph } from "@eulergraph/index"
import { EulerGraphEngineContext } from "@engineContext"
import { EulergraphCanvas } from "./EulergraphCanvas/EulergraphCanvas"
const SERVICES = [
"Editor",
"Stencil",
"DrawService",
"SaveService",
"LayersManager",
] as const
export function App() {
const [eulerEngine, setEulerEngine] = useState<EulerGraph | null>(null)
const onEngineSet = useCallback((engine: EulerGraph | null) => {
if (engine) {
engine.enableServices([...SERVICES])
}
setEulerEngine(engine)
}, [])
const onStart = useCallback((engine: EulerGraph) => {
engine.registerStandardLibs()
engine.services.Stencil?.loadLibs()
}, [])
return (
<EulerGraphEngineContext.Provider value={eulerEngine}>
<EulergraphCanvas onEngineSet={onEngineSet} onStart={onStart} />
</EulerGraphEngineContext.Provider>
)
}
Компонент src/renderer/src/EulergraphCanvas/EulergraphCanvas.tsx создаёт new EulerGraph({ container }) при mount.
Хук src/renderer/src/hooks/useEngine.ts подписывается на started:
engine.on("started", () => {
const scene = engine.addScene()
engine.setCurrentScene(scene.pageName)
engine.fitToWidth(0)
onStart(engine) // регистрация libs — здесь вызывается ваш callback из App
setIsLoading(false)
})
Доступ к engine из дочерних компонентов:
import { useContext } from "react"
import { EulerGraphEngineContext } from "@engineContext"
const engine = useContext(EulerGraphEngineContext)
engine?.render()
const engine = new EulerGraph({ container })
engine.enableServices(["Editor", "Stencil"])
engine.on("started", () => {
const scene = engine.addScene()
engine.setCurrentScene(scene.pageName)
engine.registerStandardLibs()
engine.services.Stencil?.loadLibs()
engine.fitToWidth(0)
})
started отработалоengine.currentScene не nullengine.getActiveServices() содержит нужные сервисыengine.services.Stencil?.getSortedLibGroups() возвращает группы библиотекselect — можно выделить элемент (если добавлен на сцену)| Симптом | Решение |
|---|---|
| Stencil пустой | Вызвать registerStandardLibs() и loadLibs() |
| Нельзя редактировать | Нет сервиса Editor в enableServices |
currentScene null |
Не вызваны addScene / setCurrentScene после started |
| Сервисы undefined | enableServices не вызван или engine ещё null в Context |
| Движок пересоздаётся | Не передавать нестабильные callbacks без useCallback в EulergraphCanvas |
| Файл | Что смотреть |
|---|---|
src/renderer/src/App.tsx |
enableServices, onEngineStart, external libs |
src/renderer/src/hooks/useEngine.ts |
подписки на события, started |
src/renderer/src/EulergraphCanvas/EulergraphCanvas.tsx |
создание engine |
src/engine/tests/e2e/helpers/appendEditor.ts |
минимальный vanilla |