Programmatic pixel art for JavaScript.
Build sprites and animations from arrays or compact Base64 pixel strings, then render them as SVG, PNG, GIF, or Canvas from the same JSON source.
- One canonical JSON document model for every output.
- Programmatic authoring from numeric arrays, compact strings, or shareable JSON files.
- Built-in 64-slot palette keyed to the Base64 character set, including transparency at slot
0. - Browser-first runtime plus Node-friendly rendering for docs, pipelines, and asset generation.
- Inline HTML support through
<pixel-art>.
npm install @ibimspumo/pixelscript| SVG | PNG | GIF |
import { createAnimation, renderGIF, renderPNG, renderSVG } from '@ibimspumo/pixelscript';
const comet = createAnimation({
width: 6,
height: 3,
frames: [
{ pixels: [0, 0, 0, 6, 1, 0, 0, 0, 6, 1, 0, 0, 0, 6, 1, 0, 0, 0] },
{ pixels: [0, 0, 6, 1, 0, 0, 0, 6, 1, 0, 0, 0, 6, 1, 0, 0, 0, 0] }
],
animation: { fps: 8, loop: true }
});
const svg = renderSVG(comet, { scale: 18 });
const png = await renderPNG(comet, { scale: 18 });
const gif = await renderGIF(comet, { scale: 18, iterations: 'infinite' });|
Ghost Wave JSON |
Pixel Buddy JSON |
Potion Brew JSON |
Flower Spark JSON |
PixelScript stores each frame as a compact row-major string over the Base64 alphabet. That keeps the source small, diffable, and easy to share.
{
"version": 1,
"width": 8,
"height": 8,
"palette": {
"kind": "default64",
"name": "PixelScript-64"
},
"frames": [
{
"pixels": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
}
],
"meta": {
"name": "PixelScript-64 Grid"
}
}Ais palette index0, reserved for transparency.Bis palette index1, the first visible slot.- The full built-in palette is visualized above and can be replaced with custom palettes up to 64 entries.
import {
createArt,
createAnimation,
mountPixelArt,
renderPNG,
renderSVG
} from '@ibimspumo/pixelscript';
const checker = createArt({
width: 2,
height: 2,
pixels: [0, 1, 0, 1]
});
const beacon = createAnimation({
width: 4,
height: 4,
frames: [
{ pixels: 'ABABABABABABABAB', durationMs: 120 },
{ pixels: 'BABABABABABABABA', durationMs: 120 }
],
animation: {
fps: 8,
loop: true
}
});
const svg = renderSVG(checker, { scale: 24 });
const png = await renderPNG(checker, { scale: 24 });
const controller = mountPixelArt(document.querySelector('#target'), beacon, {
render: 'canvas',
scale: 20,
autoplay: true
});
const firstPixel = controller.getPixel(0, 1, 1);
console.log('Frame 0, pixel (1,1):', firstPixel);
controller.setPixel(0, 4, 4, 8);
controller.setPixels(0, [
{ x: 3, y: 3, paletteIndex: 2 },
{ x: 4, y: 3, paletteIndex: 3 }
]);
controller.play({ iterations: 2 });<script src="./dist/pixelscript.min.js"></script>
<pixel-art
render="gif"
scale="18"
autoplay
loop
src="./docs/readme-assets/comet-burst.json"
></pixel-art>Module usage can register the element explicitly:
import { registerPixelArtElement } from '@ibimspumo/pixelscript/element';
registerPixelArtElement();Pointer interactions are supported on <pixel-art render="canvas">:
pixelscript:pixel-hoverpixelscript:pixel-enterpixelscript:pixel-leavepixelscript:pixel-downpixelscript:pixel-uppixelscript:pixel-clickpixelscript:pixel-dragpixelscript:pixel-holdpixelscript:pixel-changewhen pixels are changed programmatically
const hero = document.querySelector('pixel-art#hero-art');
hero.addEventListener('pixelscript:pixel-click', (event) => {
const detail = event.detail;
console.log('clicked pixel', detail.sourceX, detail.sourceY, detail.paletteIndex);
hero.setPixel(detail.sourceX, detail.sourceY, 0);
});
hero.addEventListener('pixelscript:pixel-change', (event) => {
const detail = event.detail;
console.log('pixel changed', detail.previousIndex, '->', detail.paletteIndex, 'at', detail.sourceX, detail.sourceY);
});Every visual in this README is generated from PixelScript documents in docs/readme-assets:
That same JSON can be used in:
- JavaScript code
- inline HTML via
dataorsrc - docs generation
- static asset pipelines
createArt(input)createAnimation(input)parseDocument(json)validateDocument(json)stringifyDocument(doc)parseCompact({ width, height, pixels, palette? })fromArray({ width, height, pixels, palette? })getDefaultPalette()definePalette({ name?, colors })validatePalette(palette)renderSVG(doc, options)renderCanvas(doc, options)renderPNG(doc, options)renderGIF(doc, options)renderDataURL(doc, options)mountPixelArt(target, doc, options)registerPixelArtElement()PixelArtControllerAPIs returned bymountPixelArtgetPixel(frameIndex, x, y)setPixel(frameIndex, x, y, paletteIndex)setPixels(frameIndex, updates)getCurrentFrame()play(options)pause()stop()seek(frameIndex)
<pixel-art>element instance methodsgetPixel(x, y, frameIndex?)setPixel(x, y, paletteIndex, frameIndex?)setPixels(updates, frameIndex?)
npm install
npm run dev
npm run typecheck
npm test
npm run readme:assetsREADME visuals are generated by scripts/generate-readme-assets.mjs.
- Demo/docs app: demo/main.ts
- JSON schema: schema/pixelscript.schema.json
- Example docs: examples/checker.json, examples/comet.json
- GitHub Pages demo:
https://ibimspumo.github.io/PixelScript/
MIT