A Svelte component wrapper for p5.js sketches.
⚠️ Warning p5.js 2.0+ has a slightly different API than older versions. In the new version, asset preloading is done in
setupinstead of thepreloadfunction.
npm i @sveltecraft/p5-svelte p5
If you want to copy-paste standard p5.js examples without the p. prefix, use the p5 attachment function with Svelte's {@attach} directive:
<script>
import { p5 } from '@sveltecraft/p5-svelte';
let x = 0;
let y = 0;
let diameter = $state(50);
function setup() {
createCanvas(800, 600);
noStroke();
}
function draw() {
background(10);
x = lerp(x, mouseX, 0.05);
y = lerp(y, mouseY, 0.05);
fill(255);
circle(x, y, diameter);
}
</script>
<div {@attach p5({ setup, draw })}></div>
<label>
diameter
<input type="range" bind:value={diameter} min={10} max={200} />
{diameter}
</label>
The p5() function runs p5 in its native global mode — all p5 methods (createCanvas, background, fill, …) and properties (mouseX, mouseY, width, height, …) are available as globals. The attachment lifecycle is managed automatically by Svelte (mounts with the element, cleans up on unmount).
TypeScript: p5 global functions are injected at runtime, so your editor may report them as unknown. Install
@types/p5and add/// <reference types="@types/p5/global" />to your entry point for full type support.
Import the P5Sketch component and the optional Sketch type. After that create a sketch function with a setup and draw function. Since we're using instance mode we have to prefix any p5 method with p which we receive as an argument:
<script lang="ts">
import P5Sketch, { type Sketch } from '@sveltecraft/p5-svelte';
let x = 0;
let y = 0;
let diameter = $state(50);
const sketch: Sketch = (p) => {
p.setup = () => {
p.createCanvas(800, 600);
p.noStroke();
};
p.draw = () => {
p.background(4);
x = p.lerp(x, p.mouseX, 0.05);
y = p.lerp(y, p.mouseY, 0.05);
p.fill(255);
p.circle(x, y, diameter);
};
};
</script>
<P5Sketch {sketch} />
<label>
diameter
<input type="range" bind:value={diameter} min={10} max={200} />
{diameter}
</label>
You can create as many sketches as you want:
<script lang="ts">
import P5Sketch, { type Sketch } from '@sveltecraft/p5-svelte';
const walker: Sketch = (p) => {
// ...
};
const randomNumberDistribution: Sketch = (p) => {
// ...
};
</script>
<!-- walker -->
<P5Sketch sketch={walker} />
<!-- random number distribution -->
<P5Sketch sketch={randomNumberDistribution} />
If you want to abstract your code into a class or function keep in mind you have to pass the p5 object to it:
<script lang="ts">
import type p5 from 'p5';
class Walker {
p: p5;
x = 0;
y = 0;
constructor(p: p5) {
this.p = p;
this.x = this.p.width / 2;
this.y = this.p.height / 2;
}
show() {
this.p.stroke(255);
this.p.point(this.x, this.y);
}
step() {
let xstep = this.p.random(-1, 1);
let ystep = this.p.random(-1, 1);
this.x += xstep;
this.y += ystep;
}
}
const sketch: Sketch = (p) => {
let walker: Walker;
p.setup = () => {
walker = new Walker(p);
p.createCanvas(400, 400);
p.background(10);
};
p.draw = () => {
walker.step();
walker.show();
};
};
</script>
<P5Sketch {sketch} />
This section shows how to use legacy addons that only work with a global p5 instance and ones that support instance mode. You have to install addons using npm instead of using a CDN.
Addons like p5.sound work only in global mode, so we have to load them using the addons array before the sketch initializes:
<script lang="ts">
import P5Sketch, { type Sketch } from '@sveltecraft/p5-svelte';
// 🚫 this doesn't work
import 'p5.sound';
// 👍 pass your legacy addons here
const addons = [() => import('p5.sound')];
const sketch: Sketch = (p) => {
let sound: any;
p.setup = async () => {
sound = await (p as any).loadSound('/sfx.mp3');
p.createCanvas(400, 400);
};
p.draw = () => {
p.background(10);
};
p.mousePressed = () => {
sound.play();
};
};
</script>
<!-- pass the addons -->
<P5Sketch {sketch} {addons} />
Addons like p5.sound look for window.p5 at load time to extend the library. By passing addons as an array, the component:
p5 dynamicallyp5 to window.p5 before loading addonsThis ensures addons are properly registered before your sketch runs.
Addons like p5.brush support global and instance mode. You can learn how to use it by reading their docs. Here's an example of using the p5.brush addon:
<script lang="ts">
import P5Sketch, { type Sketch } from '@sveltecraft/p5-svelte';
import * as brush from 'p5.brush';
const sketch: Sketch = (p) => {
brush.instance(p);
p.setup = () => {
p.createCanvas(400, 400, p.WEBGL);
};
p.draw = () => {
// ...
};
};
</script>
<P5Sketch {sketch} />
P5Sketch Propssketch (required): A function that receives a p5 instance and defines setup and draw methodsaddons (optional): Array of async functions that load p5 addonsstyle (optional): CSS styles to apply to the canvas containerclass (optional): CSS class to apply to the canvas containerp5() Options (Global Mode)setup (optional): p5 setup function using global p5 methodsdraw (optional): p5 draw function using global p5 methodsaddons (optional): Array of async functions that load p5 addons