SveltePixi

repository·master·Indexed 41 days ago

https://github.com/mattjennings/svelte-pixi

A 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.

Tokens
32.8K
Snippets
122
Records
139
Agent score
91%

What's inside SveltePixi

  1. Provide an instance when using TilingSprite subclasses

    master

    If you are extending PIXI.TilingSprite with a custom subclass, you must pass your custom instance to the instance prop.

    Failure to do so will result in a base PIXI.TilingSprite being 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} />
  2. Handle subclasses with the instance prop

    master

    If you are extending PIXI.Container with a custom subclass, you must provide the instance prop with your custom instance.

    Because of TypeScript limitations, failing to provide the instance prop will result in a base PIXI.Container being 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} />
  3. Provide an instance when extending PIXI.Graphics with subclasses

    master

    If you are extending PIXI.Graphics with a custom subclass, you must provide the instance prop with your custom instance.

    Failure to do so will cause the component to create a base PIXI.Graphics instance 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} />
  4. How to use PerspectiveMesh with custom subclasses

    master

    If you are extending PIXI.PerspectiveMesh with your own subclass, you must provide the instance prop with your custom instance.

    Due to TypeScript limitations, if you omit the instance prop, svelte-pixi will create a base PIXI.PerspectiveMesh and 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 base PIXI.PerspectiveMesh type does not require this.

    class MyPerspectiveMesh extends PIXI.PerspectiveMesh {
      myCustomMethod() { ... }
    }
    
    const mesh = new MyPerspectiveMesh(texture)
    <PerspectiveMesh instance={mesh} />
  5. How to use the Ticker for update loops

    master

    The Application component automatically creates a Ticker that runs an update loop. You can hook into this loop in two ways:

    1. Using onTick: A function that runs on every frame. It receives the ticker object as an argument.
    2. 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}
    />
  6. Handle Svelte 4 and 5 interop caveats

    master

    When 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, only Application, Renderer, and AssetsLoader use 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 legacy on:eventname syntax.
    • 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 draw prop in Graphics) may not automatically become reactive if they rely on Svelte 4-style reactive declarations.

    To fix this when using svelte-pixi/svelte-4 in 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 $state for the reactive variables it consumes.

    <!-- Svelte 4 syntax (legacy) -->
    <Sprite on:pointermove={handlePointerMove} />
    
    <!-- Svelte 5 syntax (current) -->
    <Sprite onpointermove={handlePointerMove} />
  7. How to load textures with AssetsLoader

    master

    In Pixi v8, textures must be loaded before they are used. You can manage this in svelte-pixi using several patterns:

    Wrap your components in an AssetsLoader to 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>
  8. Use the Renderer component for custom PIXI instances

    master

    The Renderer component is an alternative to the Application component. It allows you to use a custom PIXI.Renderer instance, but unlike Application, it will not automatically start a render loop or create a root container. You must manage the render loop (e.g., using a Ticker) and the root container (the "stage") yourself.

    By default, Renderer calls PIXI.autoDetectRenderer to determine the instance. This is an asynchronous operation that triggers the oninit (Svelte 5) or on: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>
  9. Handle subclasses of PIXI.Application safely

    master

    If you are extending PIXI.Application with a custom subclass, you MUST manually create the instance and pass it to the instance prop.

    Warning: If you do not provide the instance prop, the component will create a base PIXI.Application and 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} />
  10. Using Text subclasses with the instance prop

    master

    If you are extending PIXI.Text with a custom subclass, you must provide the instance prop with your custom instance.

    Because of TypeScript limitations, failing to provide the instance prop will cause the component to create a base PIXI.Text and 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} />
  11. Provide an instance when using Mesh subclasses

    master

    If you are extending PIXI.Mesh with a custom subclass, you must provide the instance prop with your custom instance.

    If you omit the instance prop, svelte-pixi will create a base PIXI.Mesh and 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:

    1. Instantiate your custom class manually.
    2. Pass that instance to the instance prop of the <Mesh /> component.
    class MyMesh extends PIXI.Mesh {
      myCustomMethod() { ... }
    }
    
    const mesh = new MyMesh(geometry, shader)
    <Mesh instance={mesh} />