Layer
The Layer
component encapsulates a piece of your canvas rendering logic. When your layer render functions are defined reactively (with $:
), 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, `render` is updated,
// triggering a render of the current layer as well as all other
// layers on the canvas.
$: 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 registered with the on:
directive receive a CanvasLayerEvent
with properties detail.x
and detail.y
representing the coordinates of the event relative to the parent canvas, as well as detail.originalEvent
, which contains the original DOM event from the canvas
element.
<script>
import { Canvas, Layer } from 'svelte-canvas';
</script>
Â
<Canvas layerEvents>
<Layer on:click={(e) => console.log(e.detail.x, e.detail.y) />
</Canvas>
Layer
supports the following event types:
'click' | 'contextmenu' | 'dblclick' | '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.detail.originalEvent.preventDefault()
in your layer event handler.
Types
Render
The Render
interface is used to type your setup and render functions. Because types cannot be used directly with Svelte’s reactive declarations, you must define your render function with let
first.
interface Render {
(props: {
context: CanvasRenderingContext2D;
width: number;
height: number;
time: number;
}): void;
}
<script>
import { Layer, type Render } from 'svelte-canvas';
let render: Render;
$: render = ({ context }) => { ... };
</script>
Â
<Layer {render} />
CanvasLayerEvent
The CanvasLayerEvent
type is used to type event objects received by layer event handlers.
type CanvasLayerEvent = CustomEvent<{
x: number;
y: number;
originalEvent: MouseEvent | TouchEvent;
}>
<script>
import { Layer, type CanvasLayerEvent } from 'svelte-canvas';
const handleClick = (e: CanvasLayerEvent) => {
console.log(e.detail.x, e.detail.y);
};
</script>
Â
<Layer on:click={handleClick} />