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 itn 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 * as Pixi from "pixi.js";import { Assets } from "pixi.js";import type { PixiComponentProps } from "pixi-solid";import { AnimatedSprite, Container, onTick, Sprite } from "pixi-solid";import type { Ref } from "solid-js";import { splitProps } from "solid-js";
// Using the utility PixiComponentProps type to allow passing through any ContainerOptions props as well as adding a ref type to forward the ref to an internal Container.export type SkyProps = PixiComponentProps & { 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, 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()}> {/* 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()} onglobalpointermove={handlePointerMove} eventMode="static" 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, }} /> </Show> </PixiCanvas> </PixiApplication> );};