objectFit
objectFit is a utility function from pixi-solid/utils that imperatively applies object-fit style scaling and positioning to any Pixi.Container.
Unlike the ObjectFitContainer component, which wraps children and manages reactive updates automatically, objectFit is a one-shot imperative call. It is well-suited for use inside ref callbacks, createEffect, event handlers, or anywhere you need direct control over when the fit is applied.
It supports these fit modes:
contain— scale uniformly to fit within bounds, preserving aspect ratiocover— scale uniformly to fill bounds, preserving aspect ratio (may clip)fill— stretch to fill bounds exactly, ignoring aspect ratioscale-down— same ascontainbut never scales up beyond original sizenone— no scaling applied
It also supports these positions:
center(default)top,right,bottom,lefttop-left,top-right,bottom-left,bottom-right{ x: number, y: number }where0is start,0.5is center, and1is end
Import it from utils:
import { objectFit } from "pixi-solid/utils";Signature
Section titled “Signature”objectFit( object: Pixi.Container, bounds: { width: number; height: number }, fitMode: ObjectFitMode, position?: ObjectPosition,): voidThe function mutates object.scale, object.x, and object.y in place. It reads the object's local bounds via getLocalBounds() to determine the original dimensions before scaling.
Usage in a ref
Section titled “Usage in a ref”The most common use is inside a ref callback to fit a container once on mount:
import { objectFit } from "pixi-solid/utils";
<Graphics ref={(graphics) => { graphics.rect(0, 0, 200, 100).fill(0xff0000); objectFit(graphics, { width: 400, height: 300 }, "contain"); }}/>;Reactive usage with createEffect
Section titled “Reactive usage with createEffect”To re-apply whenever a signal changes, use createEffect:
import { objectFit } from "pixi-solid/utils";import { createEffect, createSignal } from "solid-js";
const [fitMode, setFitMode] = createSignal("contain");let graphicsRef;
createEffect(() => { if (!graphicsRef) return; objectFit(graphicsRef, { width: 400, height: 300 }, fitMode());});
<Graphics ref={(g) => { graphicsRef = g; g.rect(0, 0, 200, 100).fill(0xff0000); objectFit(g, { width: 400, height: 300 }, fitMode()); }}/>;Code example
Section titled “Code example”import { Container, Graphics, PixiCanvas, usePixiScreen } from "pixi-solid";import type { ObjectFitMode, ObjectPosition } from "pixi-solid/utils";import { objectFit } from "pixi-solid/utils";import type * as Pixi from "pixi.js";import type { JSX } from "solid-js";import { createEffect, createSignal } from "solid-js";
const fitModes: ObjectFitMode[] = ["contain", "cover", "fill", "scale-down", "none"];type ObjectPositionPreset = Exclude<ObjectPosition, { x?: number; y?: number }>;const positions: ObjectPositionPreset[] = [ "center", "top", "right", "bottom", "left", "top-left", "top-right", "bottom-left", "bottom-right",];
const bounds = { width: 400, height: 200 };
const DemoScene = (props: { fitMode: ObjectFitMode; objectPosition: ObjectPositionPreset }) => { const pixiScreen = usePixiScreen(); let graphicsRef: Pixi.Graphics | undefined;
createEffect(() => { if (!graphicsRef) return; objectFit(graphicsRef, bounds, props.fitMode, props.objectPosition); });
return ( <Container x={pixiScreen.width * 0.5 - bounds.width * 0.5} y={pixiScreen.height * 0.5 - bounds.height * 0.5} > <Graphics ref={(g) => { g.rect(0, 0, bounds.width, bounds.height).fill("#aeff00"); }} /> <Graphics ref={(g) => { graphicsRef = g; g.rect(0, 0, 100, 200).fill("#bc3232").circle(50, 100, 35).fill("#519d70"); objectFit(g, bounds, props.fitMode, props.objectPosition); }} /> </Container> );};
export const DemoApp = (): JSX.Element => { const [fitMode, setFitMode] = createSignal<ObjectFitMode>("contain"); const [objectPosition, setObjectPosition] = createSignal<ObjectPositionPreset>("center");
return ( <div style={{ display: "grid", gap: "0.75rem" }}> <label style={{ display: "inline-flex", gap: "0.5rem", "align-items": "center" }}> <span>Fit mode</span> <select value={fitMode()} onInput={(e) => setFitMode(e.currentTarget.value as ObjectFitMode)} > {fitModes.map((mode) => ( <option value={mode}>{mode}</option> ))} </select> </label> <label style={{ display: "inline-flex", gap: "0.5rem", "align-items": "center" }}> <span>Position</span> <select value={objectPosition()} onInput={(e) => setObjectPosition(e.currentTarget.value as ObjectPositionPreset)} > {positions.map((pos) => ( <option value={pos}>{pos}</option> ))} </select> </label> <PixiCanvas style={{ width: "100%", height: "300px" }}> <DemoScene fitMode={fitMode()} objectPosition={objectPosition()} /> </PixiCanvas> </div> );};