Pass through props
Move your mouse or touch across the canvas to change the flying speed of the bird.
Code example
Section titled “Code example”When creating custom components, it’s often useful to pass props through to underlying PixiJS components. This allows for greater flexibility by gaining access to properties such as position, scale or adding event listeners from the outside.
Instead of writing them out one by one, you can use the Pixi Options type of the object you’re passing them into.
Combined with the SolidJS splitProps helper and the spread {...props} syntax we can pass all received props or only a specific group of them down to the underlying component.
import type * as Pixi from "pixi.js";import { Assets } from "pixi.js";import { AnimatedSprite, Container, onTick, Sprite } from "pixi-solid";import type { Ref } from "solid-js";import { splitProps } from "solid-js";
// Using the Pixi ContainerOptions type to allow passing through any ContainerOptions props as well as adding a ref type to forward the ref to an internal Container.// We omit the `children` prop because the Pixi `children` prop clashes with the `children` prop needed for our JSX.export type SkyProps = Omit<Pixi.ContainerOptions, "children"> & { ref?: Ref<Pixi.Container>; flyingSpeed: number;};
export const Sky = (props: SkyProps) => { const skyTexture = Assets.get<Pixi.Texture>("sky"); const birdTextures = Assets.get<Pixi.Texture>(["bird_01", "bird_02", "bird_03", "bird_04", "bird_05", "bird_06"]);
// Splitting out flyingSpeed so we pass only the valid Container props to our Container const [, containerProps] = splitProps(props, ["flyingSpeed"]);
return ( // Spread the containerProps to pass through all valid Container options and the ref <Container {...containerProps}> <Sprite texture={skyTexture} /> <AnimatedSprite scale={0.5} textures={Object.values(birdTextures)} animationSpeed={0.4 * props.flyingSpeed} ref={(bird) => { bird.play(); let time = 0; onTick((ticker) => { time = time + ticker.deltaTime * props.flyingSpeed; bird.position.x = Math.sin(time / 90) * 20 + 60; bird.position.y = Math.cos(time / 30) * 25 + 30; }); }} /> </Container> );};import type * as Pixi from "pixi.js";import { Assets, TextureStyle } from "pixi.js";import { getPixiApp, onTick, PixiApplication, PixiCanvas, PixiStage, Text } from "pixi-solid";import { objectFit } from "pixi-solid/utils";import { createResource, createSignal, Show } from "solid-js";import birdAssetUrl_01 from "@/assets/bird_01.png";import birdAssetUrl_02 from "@/assets/bird_02.png";import birdAssetUrl_03 from "@/assets/bird_03.png";import birdAssetUrl_04 from "@/assets/bird_04.png";import birdAssetUrl_05 from "@/assets/bird_05.png";import birdAssetUrl_06 from "@/assets/bird_06.png";import skyAssetUrl from "@/assets/sky.png";import { Sky } from "./pass-through-props";
export const DemoApp = () => { const [flyingSpeed, setFlyingSpeed] = createSignal(1);
const [texturesResource] = createResource(async () => { Assets.init(); // Setting scale mode to nearest for crisp pixel art TextureStyle.defaultOptions.scaleMode = "nearest"; const assets = await Assets.load<Pixi.Texture>([ { alias: "sky", src: skyAssetUrl }, { alias: "bird_01", src: birdAssetUrl_01 }, { alias: "bird_02", src: birdAssetUrl_02 }, { alias: "bird_03", src: birdAssetUrl_03 }, { alias: "bird_04", src: birdAssetUrl_04 }, { alias: "bird_05", src: birdAssetUrl_05 }, { alias: "bird_06", src: birdAssetUrl_06 }, ]);
return assets; });
const handlePointerMove = (e: Pixi.FederatedPointerEvent) => { const notInsideCanvas = e.global.x < 0 || e.global.x > e.currentTarget.width || e.global.y < 0 || e.global.y > e.currentTarget.height; if (notInsideCanvas) return;
const speed = Math.min(Math.max((e.global.x / e.currentTarget.width) * 2, 0), 2); setFlyingSpeed(speed); }; return ( <PixiApplication background="#1099bb"> <PixiCanvas style={{ "aspect-ratio": "2/1.5" }}> <Show when={texturesResource()}> <PixiStage onglobalpointermove={handlePointerMove} eventMode="static"> {/* Here on our `Sky` custom component we can also set any valid ContainerOptions and they will be passed through to the underlying Container */} <Sky flyingSpeed={flyingSpeed()} tint={"#fff0a6"} ref={(component) => { const app = getPixiApp(); onTick(() => { objectFit(component, app.renderer, "cover"); }); }} /> <Text text={`Flying Speed: ${flyingSpeed().toFixed(2)}`} position={{ x: 10, y: 10 }} style={{ fill: "#ffffff", fontSize: 16, }} /> </PixiStage> </Show> </PixiCanvas> </PixiApplication> );};