Skip to content

rejth/svelte-canvas-layers

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

138 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Svelte Canvas Layers

Declarative canvas rendering for Svelte 4.

Svelte Canvas Layers wraps the native HTML <canvas> element with a small layer-based rendering runtime. It gives Svelte apps a component model for defining canvas layers, handling pointer events, performing hit testing, and rendering either on the main thread or inside a Web Worker.

Svelte Canvas Layers currently targets Svelte 4 only.

The repository includes a small whiteboard-style demo app built on top of the canvas layer API. It shows camera controls, editable objects, selection, arrows, and layer picking.

Why This Exists

It is a playground for the kind of architecture behind whiteboards, drawing tools, visual editors, diagrams, and canvas-based UI: a scene made of interactive layers, a camera that transforms user input into world coordinates, and UI workflows built on top of those primitives.

The project began as an exploration of the Canvas 2D API and Svelte. The browser canvas API is powerful, but it is imperative by default. Svelte Canvas Layers keeps the canvas itself native while giving Svelte apps a component model for organizing rendering and interaction.

Features

  • Svelte wrapper around HTML <canvas>
  • Declarative <Canvas> and <Layer> components
  • Direct Canvas 2D rendering through CanvasRenderingContext2D
  • Layer-level pointer, click, hover, and drag-style interactions
  • Color-based hit testing for interactive canvas objects
  • Main-thread rendering support
  • Web Worker rendering support
  • Worker-owned renderer registry
  • Built for Svelte 4

Main Thread Example

<script lang="ts">
  import { Canvas, Layer } from '@canvas/engine'

  const box = { x: 40, y: 40, width: 120, height: 80, color: 'tomato' }
</script>

<Canvas width={800} height={600} useLayerEvents>
  <Layer
    bounds={{
      x0: box.x,
      y0: box.y,
      x1: box.x + box.width,
      y1: box.y + box.height,
    }}
    render={({ ctx }) => {
      ctx.fillStyle = box.color
      ctx.fillRect(box.x, box.y, box.width, box.height)
    }}
    on:click={() => console.log('box clicked')}
  />
</Canvas>

Worker Example

<script lang="ts">
  import { WorkerCanvas, WorkerLayer } from '@canvas/engine'

  const box = { x: 40, y: 40, width: 120, height: 80, color: 'tomato' }
</script>

<WorkerCanvas
  createWorker={() =>
    new Worker(new URL('./canvas.worker.ts', import.meta.url), { type: 'module' })
  }
>
  <WorkerLayer renderer="box" data={box} />
</WorkerCanvas>
// canvas.worker.ts
import {
  exposeCanvasWorker,
  type WorkerRenderRegistry,
} from '@canvas/engine/worker-runtime'

const renderers = {
  box({ ctx, data }) {
    ctx.fillStyle = data.color
    ctx.fillRect(data.x, data.y, data.width, data.height)
  },
} satisfies WorkerRenderRegistry

exposeCanvasWorker(renderers)

Storybook

Storybook contains focused examples for the engine package, including main-thread rendering, worker rendering, color picking, layer events, pixel ratio handling, and resizable layers.

pnpm dev:storybook

Development

pnpm install
pnpm dev
pnpm check

Useful package checks:

pnpm --filter @canvas/engine check
pnpm --filter @canvas/engine build
pnpm --filter @canvas/storybook build

Deploy Builds

The app and Storybook build as separate static targets:

pnpm build:app
pnpm build:storybook
pnpm build:deploy

Outputs:

  • App: dist/app
  • Storybook: packages/storybook/dist

Preview locally:

pnpm preview:app        # app on http://localhost:4173
pnpm preview:storybook  # storybook on http://localhost:6007

About

Declarative canvas rendering for Svelte with layers, hit testing, and main-thread or Web Worker execution

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors