SveltePixi
repository·master·Indexed 41 days ago
https://github.com/mattjennings/svelte-pixiA library for creating PixiJS applications within the Svelte framework, bridging Svelte's declarative reactivity with the high-performance rendering of PixiJS. Version 8.0.1 provides components such as Application, AnimatedSprite, and AssetsLoader, with dedicated support for both Svelte 4 and Svelte 5.
What's inside SveltePixi
- SveltePixi is a library designed to allow developers to create PixiJS applications using the Svelte framework. It provides a way to bridge the declarative nature of Svelte with the imperative, high-performance rendering capabilities of PixiJS.
Provide an instance when using TilingSprite subclasses
masterIf you are extending
PIXI.TilingSpritewith a custom subclass, you must pass your custom instance to theinstanceprop.Failure to do so will result in a base
PIXI.TilingSpritebeing created and unsafely cast to your subclass type, which causes runtime errors when accessing subclass-specific properties or methods.Correct Pattern:
class MyTilingSprite extends PIXI.TilingSprite { myCustomMethod() { ... } } const sprite = new MyTilingSprite() // Pass the custom instance to the component <TilingSprite instance={sprite} />class MyTilingSprite extends PIXI.TilingSprite { myCustomMethod() { ... } } const sprite = new MyTilingSprite() <TilingSprite instance={sprite} />Handle subclasses with the instance prop
masterIf you are extending
PIXI.Containerwith a custom subclass, you must provide theinstanceprop with your custom instance.Because of TypeScript limitations, failing to provide the
instanceprop will result in a basePIXI.Containerbeing created and unsafely cast to your subclass type. This leads to runtime errors when accessing subclass-specific properties or methods that do not exist on the base instance.class MyContainer extends PIXI.Container { myCustomMethod() { ... } } const container = new MyContainer() <Container instance={container} />Provide an instance when extending PIXI.Graphics with subclasses
masterIf you are extending
PIXI.Graphicswith a custom subclass, you must provide theinstanceprop with your custom instance.Failure to do so will cause the component to create a base
PIXI.Graphicsinstance and unsafely cast it to your subclass type. This leads to runtime errors when attempting to access methods or properties unique to your subclass. This is a known limitation due to TypeScript's handling of generic types in this context.class MyGraphics extends PIXI.Graphics { myCustomMethod() { ... } } const graphics = new MyGraphics() // You MUST pass the custom instance to the component <Graphics instance={graphics} />How to use PerspectiveMesh with custom subclasses
masterIf you are extending
PIXI.PerspectiveMeshwith your own subclass, you must provide theinstanceprop with your custom instance.Due to TypeScript limitations, if you omit the
instanceprop,svelte-pixiwill create a basePIXI.PerspectiveMeshand unsafely cast it to your subclass type. This will lead to runtime errors when you attempt to access properties or methods specific to your subclass. This requirement applies only when using subclasses; using the basePIXI.PerspectiveMeshtype does not require this.class MyPerspectiveMesh extends PIXI.PerspectiveMesh { myCustomMethod() { ... } } const mesh = new MyPerspectiveMesh(texture) <PerspectiveMesh instance={mesh} />How to use the Ticker for update loops
masterThe
Applicationcomponent automatically creates aTickerthat runs an update loop. You can hook into this loop in two ways:- Using
onTick: A function that runs on every frame. It receives thetickerobject as an argument. - Using
tick: A function that returns a Svelte writable store. This store updates on every tick with the value returned by the callback, which is useful for reactive state updates in Svelte.
Both methods allow you to perform frame-by-frame logic like animations or physics updates.
<script> import * as PIXI from 'pixi.js' import { Sprite, onTick } from 'svelte-pixi' let x = $state(360) let y = $state(200) onTick((ticker) => { const time = ticker.lastTime / 500 x = 360 + Math.cos(time) * 50 y = 200 + Math.sin(time) * 50 }) </script> <Sprite texture={PIXI.Texture.from('/assets/food/lemonpie.png')} anchor={0.5} {x} {y} scale={3} />- Using
Handle Svelte 4 and 5 interop caveats
masterWhen mixing Svelte 4 and Svelte 5 components in SveltePixi, be aware of the following limitations:
Snippets vs Slots
Svelte 5 uses snippets instead of slots. While you can pass snippets to Svelte 4 components (using both
{#snippet}and standard children), named slots do not work when passing content to Svelte 5 snippets. In SveltePixi, onlyApplication,Renderer, andAssetsLoaderuse named slots; if you have custom components using named slots, they may fail when used inside Svelte 5 snippets.Event Syntax
svelte-pixi/svelte-4: Uses the legacyon:eventnamesyntax.svelte-pixi(Svelte 5 default): Uses the new callback prop syntax (e.g.,onpointermove={handler}). This is more performant as it only listens for events actually used.
Reactivity in Graphics components
In Svelte 5, functions passed as props (like the
drawprop inGraphics) may not automatically become reactive if they rely on Svelte 4-style reactive declarations.To fix this when using
svelte-pixi/svelte-4in Svelte 5: Declare the function as a reactive variable using$:.To fix this when using the standard
svelte-pixi(Svelte 5) import: Simply declare the function normally and use Svelte 5$statefor the reactive variables it consumes.<!-- Svelte 4 syntax (legacy) --> <Sprite on:pointermove={handlePointerMove} /> <!-- Svelte 5 syntax (current) --> <Sprite onpointermove={handlePointerMove} />How to load textures with AssetsLoader
masterIn Pixi v8, textures must be loaded before they are used. You can manage this in
svelte-pixiusing several patterns:1. Using AssetsLoader (Recommended)
Wrap your components in an
AssetsLoaderto ensure assets are ready before the child components render.<AssetsLoader assets={['/my-texture.png']}> <Sprite texture={'/my-texture.png'} /> </AssetsLoader>2. Using PIXI.Assets.load directly
Use a standard Svelte
{#await}block to load the texture manually.{#await PIXI.Assets.load('/my-texture.png') then texture} <Sprite {texture} /> {/await}3. Combining AssetsLoader with PIXI.Texture.from
<AssetsLoader assets={['/my-texture.png']}> <Sprite texture={PIXI.Texture.from('/my-texture.png')} /> </AssetsLoader>Use the Renderer component for custom PIXI instances
masterThe
Renderercomponent is an alternative to theApplicationcomponent. It allows you to use a customPIXI.Rendererinstance, but unlikeApplication, it will not automatically start a render loop or create a root container. You must manage the render loop (e.g., using aTicker) and the root container (the "stage") yourself.By default,
RenderercallsPIXI.autoDetectRendererto determine the instance. This is an asynchronous operation that triggers theoninit(Svelte 5) oron:init(Svelte 4) callback when complete.<script> import { Renderer, Container, Ticker } from 'svelte-pixi' let renderer let stage </script> <Renderer bind:instance={renderer} width={400} height={400}> <Ticker ontick={() => renderer.render(stage)}> <Container bind:instance={stage}> <!-- Your PIXI content here --> </Container> </Ticker> </Renderer>Handle subclasses of PIXI.Application safely
masterIf you are extending
PIXI.Applicationwith a custom subclass, you MUST manually create the instance and pass it to theinstanceprop.Warning: If you do not provide the
instanceprop, the component will create a basePIXI.Applicationand unsafely cast it to your subclass type. This will cause runtime errors when accessing subclass-specific properties or methods.Correct Pattern:
class MyApp extends PIXI.Application { myCustomMethod() { ... } } // 1. Create your instance first const app = new MyApp() // 2. Pass it to the component via the instance prop <Application instance={app} />class MyApp extends PIXI.Application { myCustomMethod() { ... } } const app = new MyApp() <Application instance={app} />Using Text subclasses with the instance prop
masterIf you are extending
PIXI.Textwith a custom subclass, you must provide theinstanceprop with your custom instance.Because of TypeScript limitations, failing to provide the
instanceprop will cause the component to create a basePIXI.Textand unsafely cast it to your subclass type. This leads to runtime errors when attempting to access methods or properties unique to your subclass.Correct pattern for subclasses:
class MyText extends PIXI.Text { myCustomMethod() { ... } } const text = new MyText() // Pass the custom instance to the component <Text instance={text} />class MyText extends PIXI.Text { myCustomMethod() { ... } } const text = new MyText() <Text instance={text} />Provide an instance when using Mesh subclasses
masterIf you are extending
PIXI.Meshwith a custom subclass, you must provide theinstanceprop with your custom instance.If you omit the
instanceprop,svelte-pixiwill create a basePIXI.Meshand unsafely cast it to your subclass type. This leads to runtime errors when attempting to access properties or methods unique to your subclass.Correct pattern for subclasses:
- Instantiate your custom class manually.
- Pass that instance to the
instanceprop of the<Mesh />component.
class MyMesh extends PIXI.Mesh { myCustomMethod() { ... } } const mesh = new MyMesh(geometry, shader) <Mesh instance={mesh} />