drincs-productions/pixi-vn/canvas

Claude Code and agent skill by drincs-productions/pixi-vn

Trust tier 3
  • community
Source check pending

Checking that the SKILL.md file is still in the repository.

Use when adding, moving, or removing images, sprites, text, or video on the Pixi'VN game canvas, or when applying or creating transitions (dissolve, fade, move, zoom, push, wipe, iris, split, flash, blur, pixelate, or a custom one built on `canvas.animate`/`filters.animate`), shake/animation effects, or ticker-based animations built on PixiJS. Covers the `canvas` singleton exported from `@drincs/pixi-vn`. For UI layers (HTML or PixiJS) mounted on top of the canvas, see `pixi-vn-ui` instead.

Install

npx vskill@latest install drincs-productions/pixi-vn/canvas

SKILL.md

Pixi'VN Canvas

The Canvas module is Pixi'VN's 2D scene graph, built directly on top of PixiJS. It manages everything that is visually rendered in the game: background images, character sprites, text, video, and the transitions/animations between them. Official docs: pixi-vn.com/start/canvas.

Every symbol used below (canvas, showImage, Sprite, transition helpers, etc.) is exported from the main package entry point:

ts
import { canvas } from "@drincs/pixi-vn";

(Also available from the narrower @drincs/pixi-vn/canvas subpath — see pixi-vn for when to prefer that.)

When to use this skill

Load this skill whenever a task involves:

  • Showing, replacing, or removing an image/sprite/video/text on screen.
  • Building a composite character sprite out of several image layers.
  • Applying a transition (dissolve, fade, move, zoom, push, wipe, iris, split, flash, blur, pixelate) when a background or sprite changes.
  • Adding a shake effect or a custom PixiJS-ticker-driven animation.
  • Reading or modifying canvas element position/anchor/alpha/zIndex.

For building/mounting UI layers (HTML or PixiJS) on top of the canvas, use pixi-vn-ui instead — this skill is about the gameLayer save-able scene graph, not UI chrome.

For dialogue/character-portrait logic use pixi-vn-characters and pixi-vn-narration instead; this skill is about the underlying rendering primitives.

Core mental model

  • `canvas` (from @drincs/pixi-vn) is the single entry-point object developers use. It wraps

a PixiJS Application and exposes methods to manage canvas elements and layers. Call await canvas.init(element, options) once at startup (this is normally done for you by Game.init(...) from the core package — see pixi-vn).

  • Elements are tracked by alias, not by variable (docs).

canvas.add(alias, component) inserts a component (an instance of Container, Sprite, ImageSprite, ImageContainer, Text, or VideoSprite) into canvas.layers.gameLayer (a single PixiJS Container that holds all "in-scene" elements) and sets component.label = alias. Use canvas.find<T>(alias) to look elements back up and canvas.remove(alias) to remove them. Aliases are also how Pixi'VN saves/restores canvas state (see pixi-vn-storage), so prefer the alias-based helpers below over holding onto raw object references across steps.

  • Every element class is a save-able extension of a PixiJS class: Container extends

PIXI.Container, Sprite/ImageSprite/VideoSprite extend PIXI.Sprite, Text extends PIXI.Text. They add a .memory getter / .setMemory() for serialization, plus convenience properties (anchor, align, percentagePosition, xAlign/yAlign, percentageX/percentageY) as alternative ways to position an element without doing pixel math.

  • `Layer` is just a type alias for a plain PIXI.Container<ContainerChild> — there's no

special Layer class. A separate, non-save-able PixiJS Container can be attached directly to the stage as a sibling of gameLayer (canvas.layers.add/get/remove) — see pixi-vn-ui for that API, it's how UI layers (HTML or PixiJS) are built on top of the canvas.

  • Tickers are how frame-based animation and effects work under the hood; canvas.animate(...)

(built on the motion library) is the high-level way to animate numeric properties over time, and it is what all the built-in transition helpers use internally. Running tickers are managed through the separate `tickers` singleton (also from @drincs/pixi-vn, not a member of canvas — the old canvas.tickers is a deprecated alias of it).

Showing and removing an image

ts
import { canvas, addImage, showImage } from "@drincs/pixi-vn";
// addImage() creates + registers the sprite but does NOT load/display the texture yet
const bunny1 = addImage("bunny1"); // "bunny1" is an alias registered in the assets manifest
await bunny1.load();
// showImage() is addImage() + load() in one call
const bunny2 = await showImage("bunny2");
bunny2.anchor = 0.5;
bunny2.x = canvas.width / 2;
bunny2.y = canvas.height / 2;
// remove it later by alias
canvas.remove("bunny1");

Always pass a manifest alias (as above), not a raw URL/path — see pixi-vn-assets for how assets get registered (local vs. online) and loaded. addImage/showImage do also accept a raw URL as a second argument for quick prototyping, but that couples code to a specific file location; addImage/showImage throw a PixiError if neither a URL nor a registered alias resolves. Both return an ImageSprite.

For a composite image made of multiple stacked textures (e.g. a character body + outfit + face), use ImageContainer via addImageCointainer / showImageContainer (note the exported spelling "Cointainer"):

ts
import { showImageContainer } from "@drincs/pixi-vn";
const liam = await showImageContainer("liam", ["liam-body", "liam-head"]);

Adding text

ts
import { showText } from "@drincs/pixi-vn";
showText("score-label", "Score: 0", {
fontSize: 24,
fill: "white",
x: 20,
y: 20,
});

showText(alias, text, options) creates/replaces a Text element (extends PIXI.Text) and adds it to the canvas immediately. options is TextOptions (PixiJS CanvasTextOptions plus the align/percentagePosition positioning extensions), so style, fontSize, fill, x/y, etc. all work as in plain PixiJS.

Playing a video

ts
import { showVideo } from "@drincs/pixi-vn";
const film = await showVideo("intro-film"); // "intro-film" resolves via the assets manifest
film.loop = true;
// film.pause(), film.play(), film.restart(), film.currentTime = 2

addVideo/showVideo mirror addImage/showImage and return a VideoSprite (extends ImageSprite). Files are also recognized as videos by extension automatically anywhere a transition helper accepts an image URL (.mp4, .webm, .mov, etc. — see checkIfVideo).

Transitions

Docs: pixi-vn.com/start/canvas-transition.

All transition helpers take (alias, componentOrUrl?, props?, priority?). If you omit the component/URL argument, the alias itself is used as the texture URL/alias. Each function replaces (or removes) whatever is currently registered under alias, transferring position and running tickers from the old element automatically. They all return a Promise (or array) of ticker ids you can pass to tickers.forceCompletion if you need to await completion, but usually you just call and move on.

ts
import {
showWithDissolve,
removeWithDissolve, // fade the new image in / fade the current one out
showWithFade,
removeWithFade, // cross-fade old -> new (falls back to dissolve if none exists)
moveIn,
moveOut, // slide in/out from a screen edge
zoomIn,
zoomOut, // scale in/out from a screen edge
pushIn,
pushOut, // new image pushes the old one off-screen
} from "@drincs/pixi-vn";
// change background with a 1s dissolve ("bg-forest" is a manifest alias)
await showWithDissolve("background", "bg-forest", { duration: 1 });
// slide a character sprite in from the left
await moveIn("liam", "liam-neutral", { direction: "left", duration: 0.5 });
// remove a character with a zoom-out toward the right edge
zoomOut("liam", { direction: "right", duration: 0.5 });

props extends AnimationOptions from motion (e.g. duration, ease) plus a completeOnContinue flag (default true) that finishes the transition immediately when the player advances the narration before the animation ends — leave this at its default unless you specifically want an animation to be interruptible/ignored.

Generic reveal/filter transitions: wipe, iris, split, flash, blur, pixelate, glitch, twist, warp, ripple, noiseDissolve, tv, pinch

These are only exposed through the transitions namespace (no flat top-level export like the older moveIn/showWithDissolve), each as a matched xIn/xOut pair with the same (alias, componentOrUrl?, props?, priority?) / (alias, props?, priority?) shapes as above. They favor a handful of configurable options over narrative-specific variants — e.g. there's one wipeIn, not wipeLeft/wipeRight.

ts
import { transitions } from "@drincs/pixi-vn";
// wipe: a moving boundary reveals/conceals the image. `angle` in degrees (0 = left-to-right, 90 =
// bottom-to-top, ...); `direction` ("up"/"down"/"left"/"right") is a shorthand for the 4 cardinal angles.
await transitions.wipeIn("background", "bg-forest", {
direction: "left",
duration: 1,
});
await transitions.wipeIn("background", "bg-night", { angle: 45, duration: 1 }); // diagonal wipe
transitions.wipeOut("background", { angle: 180, invert: true, duration: 1 });
// iris: an expanding/contracting radial mask. `origin` is normalized (0-1) to the element's own bounds.
await transitions.irisIn("liam", "liam-happy", {
origin: { x: 0.5, y: 0.3 },
duration: 0.8,
});
transitions.irisOut("liam", { aspect: 2, duration: 0.8 }); // aspect > 1 = wide ellipse instead of a circle
// split: two mask panels move apart/together - covers "curtain" effects without a dedicated API.
await transitions.splitIn("background", "bg-forest", {
orientation: "horizontal",
duration: 1,
});
transitions.splitOut("background", {
orientation: "vertical",
origin: 0.3,
duration: 1,
});
// flash: a configurable color overlay (not just white) fades in/hold/out, optionally pulsing.
await transitions.flashIn("background", "bg-forest", { duration: 0.15 }); // white camera-flash reveal
transitions.flashOut("liam", {
color: 0xff0033,
holdDuration: 0.05,
pulses: 3,
duration: 0.1,
}); // red damage flash
// blur / pixelate: the image is shown already blurred/pixelated and resolves into focus (or the reverse for *Out).
await transitions.blurIn("liam", "liam-happy", { strength: 40, duration: 1 });
transitions.blurOut("liam", { duration: 1 });
await transitions.pixelateIn("background", "bg-forest", {
pixelSize: 48,
duration: 1,
});
transitions.pixelateOut("background", { duration: 1 });
// glitch: jittery slices + red/blue split, settling on *In, building up on *Out.
await transitions.glitchIn("liam", "liam-happy", { strength: 40, bursts: 3 });
// twist: unwinds out of (or winds into) a swirl - `angle` in degrees, `origin` normalized.
transitions.twistOut("liam", { angle: 540 });
// warp: radial zoom-blur streaks, like dropping out of / jumping into hyperspace.
await transitions.warpIn("background", "bg-space", { strength: 0.6 });
// ripple: fades in/out through a spreading water ring - dreams, magic, memories.
await transitions.rippleIn("liam", "liam-dream", {
origin: { x: 0.5, y: 0.3 },
});
// noiseDissolve: the classic VN image dissolve - organic noise blotches (`edge: "soft"` for a cloudy fade).
await transitions.noiseDissolveIn("background", "bg-night", {
edge: "hard",
noiseScale: 8,
});
// tv: old TV switching on (dot -> glowing line -> image) / off; scales around the anchor (center it).
transitions.tvOut("liam", { lineThickness: 0.02, brightness: 3 });
// pinch: emerges from / is sucked into a point (`mode: "bulge"` puffs out instead).
transitions.pinchOut("liam", { mode: "pinch" });
// move/push also take an optional motion-blur trail (true = 40px, or a length in pixels).
await transitions.moveIn("liam", "liam-happy", {
direction: "right",
duration: 0.6,
motionBlur: true,
});

Distortion transitions (glitch, twist, warp, ripple, pinch) move pixels around, so they read best on images with detail - on a flat, single-color element they're much less visible.

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 95 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
137
Repository forks
8
Repository npm downloads, 7 days
468
7-day trend score
41

Stars and forks are for the whole GitHub repository, not this skill alone. Downloads are for the repository's npm package. Refreshed 15 Aug 2026, 2 months ago.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/drincs-productions/pixi-vn/canvas/badge)](https://verified-skill.com/skills/drincs-productions/pixi-vn/canvas)

Something wrong with this skill or its page? Tell us.