ludic-canvas

中文文档
0.10.0发布于 2026/11/04MITTypeScriptES Module构建来源已验证

React interfaces for browser games, powered by Yoga WebAssembly and WebGL.

原始使用文档
文档目录13 节
  1. Install
  2. Start a project (0.4.0+)
  3. Shared controls
  4. Font atlas CLI (0.2.0+)
  5. First interface
  6. Playable integration examples
  7. Architecture
  8. Development
  9. Publishing
  10. Compatibility and scope
  11. License
  12. 3D example project
  13. Large collections

Ludic Canvas

React interfaces for browser games, powered by Yoga WebAssembly layout and WebGL rendering.

Documentation · Guide · API reference

Compose HUDs, menus and inventories with four typed primitives: View, Text, Image and Line. Use React state, effects and context while the renderer computes flexbox layout in WebAssembly and paints batched GPU primitives with crisp MSDF text.

Controlled Button, Switch, Slider, Tab, Tabs, Dialog and ScrollArea components share interaction behavior while leaving their layout, colors and contents to your game. Explore the component catalogue.

Version 0.7.0 adds controlled TextInput and TextArea native editors for topmost form panels and dialogs. See the native editing contract for fonts, layering, composition and qualification limits. These fields require ludic-canvas 0.7.0 or later.

Version 0.9.0 includes an experimental portable core and macOS proof: the same React components run with Hermes, native Yoga and Skia/Metal. This work remains experimental. See the architecture and build instructions and qualification results. Android, iOS, Windows and Linux hosts remain future work.

Install

The npm package includes JavaScript, TypeScript declarations, a precompiled Yoga reactor, a default OFL font atlas, the portable font atlas compiler and license notices.

npm install ludic-canvas [email protected]

Releases use the Changesets version-PR workflow described in docs/RELEASING.md.

Start a project (0.4.0+)

npx ludic-canvas@latest init my-game --template canvas2d
cd my-game
npm install
npm run dev

Choose --template three for a Three.js world. Both starters include a transparent UI overlay, controlled HUD, application-owned simulation/frame loop, responsive canvas sizing, a licensed font, font generation before development/build, and resource teardown. The initializer accepts new or empty directories and never installs dependencies automatically. Use npm run build to generate dist/.

Replace fonts/Interface.ttf and edit ludic-canvas.fonts.json to bring your own licensed TTF, OTF, WOFF or WOFF2 font. Imported atlas URLs support deployments under a URL prefix. See the initializer guide.

Shared controls

import { useState } from 'react';
import { Switch, Text } from 'ludic-canvas';

function Hints() {
  const [enabled, setEnabled] = useState(true);
  return (
    <Switch label="Navigation hints" checked={enabled} onCheckedChange={setEnabled} style={{ padding: 16 }}>
      <Text>{enabled ? 'Hints on' : 'Hints off'}</Text>
    </Switch>
  );
}

Values remain controlled by the application. Slider render functions receive a normalized ratio for custom tracks/thumbs. Tabs manage one keyboard Tab stop and skip disabled entries. Dialogs isolate input and restore focus through nested scopes. ScrollArea provides vertical wheel/touch scrolling and focus reveal. useUIRoot() accesses the owning root inside ui.render(); separate roots keep their own focus, React state and resources. No global active root is used.

Font atlas CLI (0.2.0+)

The package includes a portable CLI:

npx ludic-canvas fonts --init
# Set the font source paths in ludic-canvas.fonts.json
npx ludic-canvas fonts --config ludic-canvas.fonts.json
{
  "$schema": "https://libraries.ludic-canvas.victorqueiroz.dev/font-atlas.schema.json",
  "output": "public/fonts",
  "fonts": [
    {
      "name": "interface",
      "source": "fonts/Interface.woff2",
      "size": 48,
      "distanceRange": 6
    }
  ]
}

Inputs are single-face outline TTF, OTF, WOFF and WOFF2 fonts, including variable fonts configured with axis tags such as "variations": { "wght": 600 }. Paths are relative to the configuration file. The CLI generates an MTSDF PNG, JSON metrics and a cache manifest. Register the PNG/JSON through createUI({ fonts }). No native compiler, external executable or network connection is needed after installation.

Add the CLI command to your project's predev and prebuild scripts to generate only when inputs change. Use --force to rebuild. See the font CLI guide for character coverage, variable fonts and diagnostics.

First interface

Open the minimal counter in StackBlitz or run the standalone example. It installs the published package and uses its bundled font and layout WASM without native build tools. See the tested consumer configurations for development startup and browser verification.

Give the canvas a nonzero CSS width and height inside a positioned parent. Then use automatic JSX compilation:

import { createUI, View, Text } from 'ludic-canvas';

const ui = await createUI({ canvas });

ui.render(
  <View style={{ padding: 24, gap: 12 }}>
    <Text style={{ fontSize: 28 }}>Ready to play</Text>
    <View
      label="Start game"
      onPress={() => startGame()}
      style={{ padding: 16, background: '#526dff', borderRadius: 8 }}
    >
      <Text>Start game</Text>
    </View>
  </View>,
);

// On scene teardown:
ui.destroy();

Playable integration examples

The Play gallery offers selectable thumbnails, one active game viewport and integration notes for each example.

Orbital Relay is a small courier game with a Canvas 2D world and a transparent Ludic Canvas HUD. It includes cargo collection and delivery, collisions, boost, pause and replay, a responsive manifest, and keyboard/touch controls.

The example source uses only public library exports. Its interface and mission modules each define a font family and a CLI configuration. The application root composes both FontSource values, keeps simulation state outside React, and drives ui.frame(now) from the game loop.

npm run fonts:game    # regenerate Oxanium and Space Mono atlases
npm run dev           # open /play/ or play inside the homepage

Architecture

React components and hooks
          ↓
Retained host tree + input
          ↓
Yoga 3.2.1 layout in WebAssembly
          ↓
Painter, animation and hit testing
          ↓
WebGL 1 batches + MSDF font atlases

The library owns layout, rendering, animation and input. Your application owns game state, simulation, persistence, audio and assets. Supply image URLs or a resolver, register font atlases, and customize theme tokens. No game schema, asset catalog or ECS is bundled.

Automatic drawing starts by default. For a game-owned loop, pass autoStart: false and call ui.frame(now) after the game renders. A transparent overlay canvas works independently of the game's renderer. Advanced WebGL 1 integrations may supply a shared context; the UI changes GL state and the engine must reset its state cache before its next pass.

Development

Node 24 or newer:

npm ci
npm run dev           # documentation and interactive examples
npm run check         # types, real WASM/React tests, docs, distribution audit
npm run format:check
npx playwright install --with-deps
npm run test:browser  # Chromium, Firefox, WebKit and mobile emulation
npm pack              # installable release tarball

The documentation uses Vite and static HTML for crawlable guides and an API reference generated from emitted TypeScript declarations. Its live examples consume the built package's public exports.

See CONTRIBUTING.md for the source map, generated documentation, focused browser checks, CI troubleshooting and evidence procedures. The dated session handoff records verified state and remaining work.

Rebuild the optional native tools:

npm run toolchain -- --llvm /path/to/llvm
npm run wasm
npm run fontgen:wasm
npm run fonts:example

Yoga uses C++23, CMake 3.28+, raw Clang/LLVM and wasm-ld, with SHA-256-pinned Yoga and WASI toolchain downloads. Emscripten is not used. The portable font compiler builds pinned msdf-atlas-gen, FreeType and Brotli sources into a WASI command. Consumers run the included compiler with Node and do not need native tools.

Publishing

Run npm run changeset for publishable behavior changes. Merges to main open or update a version PR. Merging the version PR publishes through npm OIDC, with provenance, after Linux/macOS/Windows checks pass. The workflow creates tags and GitHub releases and skips versions already present on npm.

See docs/RELEASING.md for the routine release procedure, npm run verify:release, deployment verification and historical owner setup. No npm token is stored in GitHub secrets.

Compatibility and scope

Ludic Canvas targets desktop and mobile browser games. React 19.3.1 is the tested peer version; react-reconciler 0.34.0 is pinned because its host API is unstable. The browser needs WebGL 1, WebAssembly SIMD/bulk-memory, createImageBitmap and Pointer Events.

The runtime supports captured pointer/key events, vertical wheel/touch scrolling, scoped hotkeys, modal focus scopes, spatial focus navigation, DOM control/group semantics, polite live announcements, text scaling and reduced motion. The mirror is a limited accessibility aid rather than a complete semantic document.

Text uses pre-baked glyphs, atlas pair kerning and greedy wrapping. A string or ordered array in fontFamily selects registered faces; each glyph uses the first face containing it. All selected faces share a baseline and fallback metrics can increase line height. Set fontKerning: 'none' to disable pair adjustments. Complex-script/GPOS shaping, bidi, grapheme-aware wrapping, editable canvas text, shared WebGL 2 contexts and native engine bindings remain unimplemented. Up to four font atlases are supported per root. See the production review and support matrix.

const ui = await createUI({
  canvas,
  fonts: [interfaceFont, symbolsFont],
  onFontDiagnostic: (diagnostic) => console.warn(diagnostic.message),
});
ui.render(<Text style={{ fontFamily: ['interface', 'symbols'] }}>Café · Ready</Text>);

Use the names in your FontSource values. A missing glyph becomes ? in the primary face and can produce an opt-in diagnostic, once per codepoint/ordered chain, capped at 1024 reports per root. Regenerate an atlas when changing charset coverage. The CLI extracts legacy kern tables; a GPOS-only font can export zero pairs. Existing atlas JSON without a kerning array remains usable.

The performance lab runs fixed UI workloads and downloads raw samples with source/environment metadata. See measurement limits and acquisition instructions.

The roadmap defines the dedicated typography milestone and the physical-device qualification protocol separates automated correctness checks from hardware and assistive-technology evidence.

License

MIT © Victor Queiroz. The bundled font uses the SIL Open Font License. See THIRD_PARTY_NOTICES.md and licenses/.

3D example project

Play Kestrel Survey or run the independent example project. It combines a procedural Three.js world with a fully custom Ludic Canvas interface: projected site labels, mission cards, telemetry, minimap, camera controls, modal menus and a mobile site picker.

cd examples/kestrel-survey
npm install
npm run dev

Large collections

VirtualList provides fixed-height single-select collections with stable keys, overscan, controlled selection and logical keyboard/gamepad focus. Ordinary ScrollArea regions can expose independent typed scroll handles. See the collection guide, full contract, and the 4,000-record archive inside Kestrel Survey. The performance lab compares matched retained/windowed workloads and preserves raw measurements.

Browser roots automatically use native overflow containing rendered canvas tiles for supported scrolling panels. The browser supplies momentum while React, Yoga and the application's frame loop retain their existing ownership. Use scrollMode="canvas" per region or scrollMode: 'canvas' in createUI to select canvas presentation. Shared contexts, custom gestures and unsupported layouts fall back automatically. See the scrolling contract for the support boundary, tile budget and snapshot timing.

版本与发布记录

ludic-canvas 共发布 13 个版本,首次发布于 2026/10/27;过去 12 个月发布了 13 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.10.0latest2026/11/041 天前
0.9.02026/11/013 天前
0.8.02026/11/014 天前
0.7.02026/10/306 天前
0.6.02026/10/288 天前
0.5.02026/10/278 天前

关于 ludic-canvas 的常见问题

ludic-canvas 是什么?

React interfaces for browser games, powered by Yoga WebAssembly and WebGL.

如何安装 ludic-canvas?

在项目目录运行 npm install ludic-canvas,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:react(19.3.1)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。它还提供命令行工具 ludic-canvas,可以用 npx ludic-canvas 直接运行。

ludic-canvas 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

ludic-canvas 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

ludic-canvas 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=24。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

ludic-canvas 可以商用吗?

ludic-canvas 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

ludic-canvas 还在维护吗?

最新版本 0.10.0 发布于 2026/11/04(1 天前);至今共发布 13 个版本,其中过去 12 个月发布了 13 个;首次发布于 2026/10/27。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。