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 utility type PixiComponentProps which contains props for the PixiJS Container but you can extend it by passing in the specific component type a generic PixiComponentProps<Pixi.SpriteOptions>.
It may be useful to combine with the built in Omit or Pick utility types to exclude or include specific props.
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 { PixiComponentProps } from "pixi-solid";import { AnimatedSprite, onTick, Container } from "pixi-solid";import type * as Pixi from "pixi.js";import { Assets } from "pixi.js";import { splitProps } from "solid-js";
// Using the utility PixiComponentProps type to allow passing through any ContainerOptions props by default or accepts a generic for the specific Pixi component options we want to support.export type BirdProps = Pick<PixiComponentProps, "position" | "x" | "y" | "angle" | "scale"> & { flyingSpeed: number;};
export const Bird = (props: BirdProps) => { 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 AnimatedSprite const [, containerProps] = splitProps(props, ["flyingSpeed"]);
return ( // Spread the containerProps to pass through all valid Container options and the ref <Container {...containerProps}> <AnimatedSprite textures={Object.values(birdTextures)} animationSpeed={0.4 * props.flyingSpeed} autoPlay={true} anchor={0.5} ref={(bird) => { let time = 0; onTick((ticker) => { time = time + ticker.deltaTime * props.flyingSpeed; bird.position.x = Math.sin(time / 90) * 20; bird.position.y = Math.cos(time / 30) * 25; }); }} /> </Container> );};import { PixiCanvas, Text, usePixiScreen, Sprite } from "pixi-solid";import { ObjectFitContainer } from "pixi-solid/utils";import type * as Pixi from "pixi.js";import { Assets, TextureStyle } from "pixi.js";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 { Bird } from "./pass-through-props";
const DemoComponent = () => { const [flyingSpeed, setFlyingSpeed] = createSignal(1); const pixiScreen = usePixiScreen();
const [texturesResource] = createResource(async () => { await 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 > pixiScreen.width || e.global.y < 0 || e.global.y > pixiScreen.height; if (notInsideCanvas) return;
const speed = Math.min(Math.max((e.global.x / pixiScreen.width) * 2, 0), 2); setFlyingSpeed(speed); }; return ( <Show when={texturesResource()}> <ObjectFitContainer width={pixiScreen.width} height={pixiScreen.height} fitMode={"cover"}> <Sprite texture={Assets.get<Pixi.Texture>("sky")} onglobalpointermove={handlePointerMove} eventMode="static" /> </ObjectFitContainer> {/* Here on our `Bird` custom component we can also set any of the ContainerOptions we picked and they will be passed through to the underlying Container */} <Bird flyingSpeed={flyingSpeed()} x={pixiScreen.width / 2} y={pixiScreen.height / 2} scale={2} /> <Text text={`Flying Speed: ${flyingSpeed().toFixed(2)}`} x={10} y={10} style={{ fill: "#ffffff", fontSize: 16, }} /> </Show> );};
export const DemoApp = () => ( <PixiCanvas style={{ "aspect-ratio": "2/1.5" }}> <DemoComponent /> </PixiCanvas>);