Reactive canvas rendering with Svelte.
npm install svelte-canvas
<script>
import { Canvas, Layer, t } from 'svelte-canvas';
$: render = ({ context, width, height }) => {
context.fillStyle = `hsl(${$t / 40}, 100%, 50%)`;
context.beginPath();
context.arc(($t / 4) % width, ($t / 4) % height, 100, 0, Math.PI * 2);
context.fill();
};
</script>
<Canvas width={640} height={640}>
<Layer {render} />
</Canvas>
If you use TypeScript, add the Render type to your reactive statement:
import { ..., type Render } from "svelte-canvas";
let render: Render;
$: render = ({ context, width, height }) => {
// ...
}
More examples:
Canvas
is the top-level element. It's a Svelte wrapper around an HTML <canvas>
element.
prop | default | description |
---|---|---|
width |
640 | Canvas width |
height |
640 | Canvas height |
pixelRatio |
window.devicePixelRatio |
Canvas pixel ratio |
style |
null |
A CSS style string which will be applied to the canvas element |
class |
null |
A class string which will be applied to the canvas element |
autoclear |
true |
If true , will use context.clearRect to clear the canvas at the start of each render cycle |
layerEvents |
false |
If true , enables event handlers on child Layer components |
method | description |
---|---|
getCanvas |
Returns a reference to the canvas DOM element |
getContext |
Returns the canvas's 2D rendering context |
redraw |
Forces a re-render of the canvas |
Layer
is a layer to be rendered onto the canvas. It takes two props, setup
and render
Both take functions with a single argument that receives an object with the properties context
, width
, and height
. context
is the 2D rendering context of the parent canvas. width
and height
are the canvas's dimensions.
setup
is optional and is called once at initialization. render
is called every time the canvas redraws.
Declaring your render
function reactively allows svelte-canvas
to re-render anytime the values that the function depends on change.
All DOM events on the <canvas>
element are forwarded to the Canvas
component, so handling an event is as simple as <Canvas on:click={handleClick}>
.
Individual Layer
instances can also handle events that fall within their bounds when the layerEvents
prop on the parent Canvas
component is true
. Event handlers registered with the on:
directive receive a CustomEvent
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 canvas
DOM event.
<script>
import { Canvas, Layer, type CanvasLayerEvent } from 'svelte-canvas';
const render = ({ context }) => {
...
};
const handleClick = (e: CanvasLayerEvent) => console.log(e.detail.x, e.detail.y)
</script>
<Canvas width={640} height={640}>
<Layer {render} on:click={handleClick} />
</Canvas>
Supported event types are 'click' | 'contextmenu' | 'dblclick' | 'mousedown' | 'mouseenter' | 'mouseleave' | 'mousemove' | 'mouseup' | 'wheel' | 'touchcancel' | 'touchend' | 'touchmove' | 'touchstart' | 'pointerenter' | 'pointerleave' | 'pointerdown' | 'pointermove' | 'pointerup' | 'pointercancel'
This is an experimental feature that may have a negative performance impact.
t
is a readable store that provides the time in milliseconds since initialization. Subscribing to t
within your render function lets you easily create animations.
Render
is a typing for your reactive statements that provides types for the Layer
component's setup
and render
functions: (canvas: CanvasRenderingContext2D, width: number, height: number)