Приложение на TypeScript, объединяющее pixi.js и Skia (CanvasKit/WASM): обёртка рендерит
PIXI.Container средствами Skia, события pointerdown/pointerup работают на обоих канвасах,
а сцену можно экспортировать в векторный PDF через Skia PDF backend.
- Обёртка
PIXI.Container→ Skia:PIXI.Graphics(rect / ellipse / circle / линииmoveTo+lineTo/ rounded),PIXI.Sprite(bitmap), все трансформации (translate / rotate / scale, вложенные контейнеры). - Два канваса бок о бок: Pixi (
forceCanvas) и Skia — для сравнения рендера. - События
pointerdown/pointerupна обоих канвасах (на Skia — hit-test по геометрии Pixi черезEventBoundary, со всплытием по дереву). - Интерактивность: кнопка «случайная фигура» + переключение преднастроенных сцен.
- Экспорт в векторный PDF (Skia PDF backend, кастомная WASM-сборка). Графика — векторные операторы, спрайты — bitmap.
- Node 22 (зафиксировано в
.nvmrc;nvm useподхватит нужную версию). - npm.
- Для сборки векторного PDF — Docker (кастомная WASM-сборка Skia).
nvm use
npm install
npm run dev # дев-сервер Vite → http://localhost:5173Прод-сборка и предпросмотр:
npm run build # типизация (tsc) + сборка в dist/
npm run preview # предпросмотр прод-сборкиТесты:
npm test # прогон (vitest)
npm run test:cov # с покрытием (порог 80% по всем метрикам)
npm run typecheck # строгая типизация без эмитаСтоковый canvaskit-wasm не содержит PDF backend — приложение работает без него (рендер +
события + UI), но кнопка «Экспорт в PDF» покажет подсказку. Чтобы включить векторный PDF, соберите
кастомный CanvasKit (нужен запущенный Docker):
cd build-skia
docker build -f Dockerfile --output type=local,dest=../wasm . # ~десятки минут, ~1–2 ГБАртефакты появятся в wasm/ (canvaskit.js + canvaskit.wasm с MakePDFDocument). Подключение:
скопируйте их в public/ (создайте каталог — Vite раздаёт его содержимое из корня сайта как /canvaskit.wasm), и при необходимости
переключите импорт в src/main.ts на кастомный модуль. Подробности и доводка — build-skia/README.md.
После сборки артефакта активируются gated-тесты src/pdf/__tests__ (проверяют реальный %PDF-
с векторной графикой).
Сборка статическая (dist/) — подойдёт GitHub Pages / Netlify / Vercel / Cloudflare Pages.
Single-threaded WASM → заголовки COOP/COEP не нужны.
Для GitHub Pages (подкаталог) задайте базовый путь:
VITE_BASE=/tz-pixi-skia/ npm run buildsrc/
pixi/PixiStage.ts # PIXI.Application({forceCanvas:true})
skia/
canvaskit-loader.ts # ленивая загрузка CanvasKit
renderScene.ts # обход дерева → SkCanvas (общий для экрана и PDF)
SkiaRenderer.ts # онскрин-рендер + кеш спрайтов
sceneTransform.ts # обновление worldTransform standalone-дерева
converters/ # matrix · color · style · graphics · sprite
events/
SkiaEventBridge.ts # pointer-события на Skia-канвасе (EventBoundary + всплытие)
interactions.ts # makeInteractive · bindPointerLogging
scenes/ # exampleScene (из ТЗ) · randomShapes · sceneSwitcher
ui/ # dom (mountLayout) · Controls
pdf/PdfExporter.ts # экспорт сцены в векторный PDF
app/createApp.ts # связывание (контроллер)
main.ts # bootstrap
build-skia/ # Dockerfile + embind SkPDF + build.sh (кастомная WASM-сборка)
docs/ARCHITECTURE.md # системная архитектура
docs/superpowers/plans/ # план реализации
Ключевое: PIXI.Container — единый
источник истины; Skia — рендер-таргет поверх него; один проход обхода рисует и в онскрин-поверхность,
и в страницу PDF (поэтому PDF идентичен превью и остаётся векторным).