Layer

The Layer component encapsulates a piece of your canvas rendering logic. Every layer re-renders when the dependencies of any layer’s render function change.

<script>
  import { text } from './store';

  // When the value of the `text` store changes, it triggers a render
  // of the current layer as well as all other layers on the canvas.
  const render = ({ context }) => context.fillText($text, 10, 10);
</script>

<Layer {render} />

Render functions are called in the order the layers are defined, so each layer will appear visually on top of the layers that precede it.

Props

render

A function that receives a props object with the following properties:

render: (props: {
  context: CanvasRenderingContext2D;
  width: number;
  height: number;
  time: number;
}): void;
<!-- Render the time since initialization, centered on the canvas. -->
<Layer render={({ context, width, height, time }) => {
    context.fillText(time, width / 2, height / 2);
}} />

setup

The setup function has the same signature as render but is only called once when the layer is initialized.

setup: (props: {
  context: CanvasRenderingContext2D;
  width: number;
  height: number;
  time: number;
}): void;

Event handling

When the layerEvents prop on the parent Canvas component is true, individual Layer instances can handle events that fall within the pixels they have rendered on the canvas. Event handlers receive a LayerEvent with properties x and y representing the coordinates of the event relative to the parent canvas, as well as originalEvent, which contains the original DOM event from the canvas element.

<script>
  import { Canvas, Layer } from 'svelte-canvas';
</script>
 
<Canvas layerEvents>
  <Layer onclick={(e) => console.log(e.x, e.y) />
</Canvas>

Layer supports the following event types:

'click' | 'contextmenu' | 'dblclick' | 'auxclick' | 'mousedown' | 'mouseenter' | 'mouseleave' | 'mousemove' | 'mouseup' | 'wheel' | 'touchcancel' | 'touchend' | 'touchmove' | 'touchstart' | 'pointerenter' | 'pointerleave' | 'pointerdown' | 'pointermove' | 'pointerup' | 'pointercancel'

Under the hood, svelte-canvas proxies all CanvasRenderingContext2D methods to a second, offscreen canvas, using a unique fill and stroke color to identify each layer. When an event occurs on the main canvas, the color of the pixel at the event coordinates is read from the offscreen canvas and used to identify the corresponding layer. The event is then re-dispatched to the Layer component.

Touch events

By default, svelte-canvas does not call preventDefault on layer touch events. To prevent touchmove events from scrolling the page, call e.originalEvent.preventDefault() in your layer event handler. Alternatively, you can style the parent canvas with touch-action: none.

Types

Render

The Render interface is used to type your setup and render functions.

interface Render {
  (props: {
    context: CanvasRenderingContext2D;
    width: number;
    height: number;
    time: number;
  }): void;
}
<script>
  import { Layer, type Render } from 'svelte-canvas';
  
  const render: Render = ({ context }) => { ... };
</script>
 
<Layer {render} />

LayerEvent

The LayerEvent type is used to type event objects received by layer event handlers.

type LayerEvent = {
  x: number;
  y: number;
  originalEvent: MouseEvent | TouchEvent;
}
<script>
  import { Layer, type LayerEvent } from 'svelte-canvas';
  
  const handleClick = (e: LayerEvent) => {
    console.log(e.x, e.y);
  };
</script>
 
<Layer onclick={handleClick} />