npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

pixi-tiledmap

v2.6.0

Published

Tiled Map Editor loader and renderer for PixiJS v8

Readme

pixi-tiledmap v2 NPM version

Load and render Tiled Map Editor maps with PixiJS v8.

v2 is a ground-up rewrite targeting PixiJS v8, with its own Tiled JSON and TMX XML parser (no external deps), full layer-type support, typed API, and ESM/CJS dual output.

Features

  • PixiJS v8 — uses the modern Assets / LoadParser extension system
  • Tiled JSON + TMX XML — full spec coverage (Tiled 1.11), both .tmj and .tmx formats
  • All layer types — tile, image, object, and group layers
  • All orientations — orthogonal, isometric, staggered, hexagonal
  • Render order — right-down, right-up, left-down, left-up
  • Infinite maps — chunk-based tile layer rendering
  • Packed tile layers — static map tiles render as PixiJS batchable mesh geometry grouped by texture source, without an external tilemap dependency
  • Tile features — animated tiles, flip/rotation flags, image-collection tilesets, tint color, tile offset, tilerendersize / fillmode
  • Object rendering — rectangles, ellipses, polygons, polylines, points, text (with underline/strikeout), tile objects
  • Object templates — automatic .tx / .tj resolution with gid remapping between template and map tileset spaces
  • Parallax scrolling — per-layer parallaxx / parallaxy and map-level parallaxorigin, composed multiplicatively through group layers, applied via TiledMap.applyParallax(cameraX, cameraY)
  • Data encoding — CSV (both .tmx and .tmj) and base64 (uncompressed, gzip, zlib)
  • External tilesets — automatic resolution via the asset loader (.tsj and .tsx)
  • Tree-shakable — ESM + CJS dual build, side-effect-free
  • Typed — comprehensive TypeScript types for the full Tiled spec

Notes on Tiled-spec coverage. zstd-compressed tile data is not supported — the browser's DecompressionStream API only exposes gzip and deflate, and this library intentionally ships with zero runtime dependencies. Wang sets and terrains are parsed and exposed on ResolvedTileset for introspection, but they are editor-only metadata with no runtime rendering behaviour.

Modernization Check (v2.0.0)

v2.0.0 is modernized for the current PixiJS ecosystem and modern TypeScript package distribution:

  • Targets PixiJS v8 via peerDependencies (pixi.js: >=8.7.0)
  • Ships ESM + CJS + TypeScript types through the exports map (import + require)
  • Uses native LoadParser integration (tiledMapLoader) instead of legacy global loader APIs
  • Declares side-effect-free package metadata ("sideEffects": false) for tree-shaking
  • Uses a modern toolchain (typescript, biome, vitest, tsdown)

Why this package stands out

  • Complete Tiled coverage in one package: JSON + TMX, all layer types, all map orientations.
  • PixiJS-native loading path: register once via extensions.add(tiledMapLoader) and load maps through Assets.
  • Performance-minded internals: batchable packed mesh-backed tile layers, chunked infinite-layer traversal, cached tile textures, and efficient GID→tileset resolution.
  • Composable renderer pipeline: layer filtering, parallax, tile visuals, and texture loading are factored so manual and loader-based usage share the same rendering behavior.
  • Production packaging: side-effect-free metadata, ESM/CJS dual output, and bundled type definitions.

Internal Model

The library keeps three concepts separate:

  • Tiled map data: TMJ JSON or TMX XML in the shape Tiled writes.
  • Resolved map IR: normalized data with defaults applied, external tilesets supplied, templates merged, GIDs decoded, and layer data decoded.
  • PixiJS rendering: a TiledMap container built from a resolved map, texture maps, layer tree rendering, packed tile meshes, tile visuals for object/animated cases, and map geometry.

The asset loader runs the complete pipeline for .tmj and .tmx files. Manual construction gives you the same pieces directly: parse to a resolved map, load textures, then construct TiledMap.

Optimization checklist (for app integrators)

If you want the best runtime behavior in your game/application:

  • Prefer .tmj for the fastest parse path when authoring allows it.
  • Preload map, tileset, and image assets with Assets before scene transitions.
  • Reuse TiledMap instances for frequently revisited scenes when possible.
  • Keep large worlds in infinite/chunked maps to avoid over-allocating one giant layer.
  • Avoid unnecessary texture churn; pass stable texture maps into TiledMap options.
  • Treat TileLayerRenderer.children as renderer internals. Static map tiles are usually Mesh children now, not one Sprite per tile.
  • Run npm run bench before and after renderer hot-path changes if you maintain a fork.
  • npm test includes a headless MagicLand visual regression that renders a real TMX + GIF tileset fixture and pixel-compares it against a checked-in reference image.

Installation

npm install pixi-tiledmap pixi.js

Quick Start — Asset Loader (recommended)

Register the loader extension once, then load .tmj (JSON) or .tmx (XML) files through Assets:

import { Application, extensions, Assets } from 'pixi.js';
import { tiledMapLoader } from 'pixi-tiledmap';

extensions.add(tiledMapLoader);

const app = new Application();
await app.init({ width: 800, height: 600 });
document.body.appendChild(app.canvas);

const { container } = await Assets.load('assets/map.tmj');
app.stage.addChild(container);

The loader auto-detects the format by file extension: .tmj → JSON, .tmx → XML.

Manual Construction

If you prefer to parse and build the display tree yourself:

import { parseMap, TiledMap } from 'pixi-tiledmap';
import { Assets, Texture } from 'pixi.js';
import type { TiledMap as TiledMapData } from 'pixi-tiledmap';

const response = await fetch('assets/map.tmj');
const data: TiledMapData = await response.json();

const mapData = parseMap(data);

const tilesetTextures = new Map<string, Texture>();
for (const ts of mapData.tilesets) {
  if (ts.image) {
    tilesetTextures.set(ts.image, await Assets.load(ts.image));
  }
}

const container = new TiledMap(mapData, { tilesetTextures });
app.stage.addChild(container);

For image layers, image-collection tilesets, and animated GIF sources, pass the corresponding texture maps through TiledMapOptions. The asset loader fills these maps automatically.

API Reference

Exports

| Export | Description | | --------------------- | ---------------------------------------------------------------- | | tiledMapLoader | PixiJS LoadParser extension — register with extensions.add() | | TiledMap | Container subclass that renders a resolved map | | TileLayerRenderer | Packed mesh-backed Container for a single tile layer | | ImageLayerRenderer | Container for a single image layer | | ObjectLayerRenderer | Container for a single object layer | | GroupLayerRenderer | Container for a group layer (recursive) | | PackedTileLayerRenderer | Internal packed tile mesh base used by TileLayerRenderer | | TileSetRenderer | Texture manager for a tileset | | parseMap(data) | Synchronous Tiled JSON → resolved IR | | parseMapAsync(data) | Async variant (required for gzip/zlib compressed data) | | parseTmx(xml) | Parse TMX XML string → TiledMap data (same shape as JSON) | | parseTsx(xml) | Parse TSX XML string → TiledTileset data | | parseTx(xml) | Parse TX XML string → TiledObjectTemplate data | | decodeGid(raw) | Decode a raw GID into tile ID + flip flags |

TiledMap Container

const map = new TiledMap(resolvedMap, {
  tilesetTextures, // Map<imagePath, Texture>
  imageLayerTextures, // Map<imagePath, Texture>
  tileImageTextures, // Map<imagePath, Texture> (image-collection tiles)
  tileImageGifSources, // Map<imagePath, GifSource> (animated image-collection tiles)
  imageLayerGifSources, // Map<imagePath, GifSource> (animated image layers)
  layerFilter, // optional (layer) => boolean, for rendering selected layers
  tileSpritePadding, // optional, defaults to 0.01 to hide fractional-scale seams
});

map.orientation; // 'orthogonal' | 'isometric' | 'staggered' | 'hexagonal'
map.mapWidth; // tile columns
map.mapHeight; // tile rows
map.tileWidth; // tile pixel width
map.tileHeight; // tile pixel height
map.getLayer('ground'); // find layer Container by name

// Parallax: call after moving your camera each frame. Layers with
// parallaxx/parallaxy < 1 move slower than the camera; layers with
// parallax 0 are pinned in screen space. Group-layer parallax composes
// multiplicatively with its children.
map.applyParallax(camera.x, camera.y);

To split a map around a player sprite, render the same resolved map twice with different layer filters:

const isOverhead = (layer: ResolvedLayer) =>
  layer.properties.some((prop) => prop.name === 'overhead' && prop.value === true);

const belowPlayer = new TiledMap(resolvedMap, {
  tilesetTextures,
  layerFilter: (layer) => !isOverhead(layer),
});

const abovePlayer = new TiledMap(resolvedMap, {
  tilesetTextures,
  layerFilter: isOverhead,
});

Object Templates

When loading through the asset loader, any object with a template field is resolved automatically — referenced .tx / .tj files are fetched in parallel and merged into the map before rendering.

For manual construction (parseMap / parseMapAsync), pass templates via ParseOptions.templates:

import { parseMap, parseTx } from 'pixi-tiledmap';

const templates = new Map();
templates.set('sign.tx', parseTx(await (await fetch('sign.tx')).text()));

const mapData = parseMap(data, { externalTilesets, templates });

Template-instance merging follows Tiled semantics: the template's object fields are the base, and the instance overrides any field it explicitly sets (name, type, size, properties, gid, shape). If the template carries an external-tileset reference whose source also exists in the map, gid is translated from the template firstgid-space to the map firstgid-space, preserving flip flags.

Migration from v1

| v1 (PixiJS v4) | v2 (PixiJS v8) | | ------------------------------------- | -------------------------------------------------------- | | PIXI.loader.add('map.tmx').load(…) | extensions.add(tiledMapLoader); Assets.load('map.tmj') | | new PIXI.extras.TiledMap('map.tmx') | const { container } = await Assets.load('map.tmj') | | Global namespace mutation | Named ESM imports | | TMX XML via tmx-parser | Built-in JSON + XML parser (no external deps) | | Tile + image layers only | All layer types |

Development

npm install
npm run build        # ESM + CJS + types via tsdown
npm run dev          # watch mode
npm run check        # Biome lint + format
npm run typecheck    # tsc --noEmit
npm test             # Build, Vitest, and MagicLand visual regression
npm run bench        # renderer hot-path benchmarks

Benchmark guidance and the current smoke baseline live in docs/BENCHMARKS.md.