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

meccha-chameleon

v0.1.0

Published

WebGL overlay that lights a 2D figure from a normal map (relief + specular), with an optional live brush-painted background and shadow layer. Floats above the page and is non-interactive.

Readme

MecchaChameleon.js

A tiny WebGL overlay that lights a 2D figure from a normal map (relief + specular highlights) and floats it above your page. It's non-interactive (pointer-events: none) — purely visual. Optionally it can paint the real page behind the figure with a live brush effect and overlay a shadow texture.

Zero dependencies. Ships as native ESM (import) and CommonJS/UMD (require and <script>), and is tree-shakeable ("sideEffects": false, no top-level side effects). The core ships no images (bring your own); optional presets with embedded images are available on demand.

Install

npm install meccha-chameleon
import MecchaChameleon from 'meccha-chameleon';

MecchaChameleon.mount({
  image: 'figure.png',           // base color PNG (with alpha)
  normalMap: 'figure-normal.png',// normal map aligned to the figure
  target: '#hero', width: 200    // anchor the figure over #hero
});

Named imports also work:

import { mount, update, unmount } from 'meccha-chameleon';

Batteries-included presets (optional)

Don't have a figure yet? Import a ready-made preset — the images come embedded as data URIs, so there's nothing to copy into public/, no bundler asset config, and no file:// / CORS texture issues:

import MecchaChameleon from 'meccha-chameleon';
import mecha1 from 'meccha-chameleon/presets/mecha1';

MecchaChameleon.mount({ ...mecha1, target: '#hero' });

Presets are separate modules: importing the core library never pulls them in, so they stay tree-shakeable. A bundler only ships a preset's images if you actually import that subpath (verified: a core-only build is ~20 KB; adding the preset adds ~2.5 MB — nothing in between).

Or with a plain script tag (global MecchaChameleon):

<script src="https://unpkg.com/meccha-chameleon"></script>
<script>
  MecchaChameleon.mount({ image: 'figure.png', normalMap: 'figure-normal.png' });
</script>

WebGL note: browsers will not load textures from file://. Serve your page over HTTP (npx http-server, Vite, etc.).

API

  • MecchaChameleon.mount(config) — create the overlay.
  • MecchaChameleon.update(partialConfig) — change parameters live (light, opacity, shadow, target…). Structural changes (brush and brush params) need a fresh mount().
  • MecchaChameleon.unmount() — remove it and detach all listeners.

Config

Two assets are required: image (base color) and normalMap.

| Key | Default | What it does | |-----|---------|--------------| | image | — | Base color PNG (with alpha). Required. | | normalMap | — | Normal map, same framing as the figure. Required. | | target | null | CSS selector (#id/.class) the figure is centered over. It tracks the element on scroll/resize. null or a missing element falls back to the viewport center. | | width | 200 | Width in px (height keeps the image aspect). | | animateLight | false | Light orbits on its own. | | lightIntensity | 0.45 | Light intensity. | | ambient | 0.22 | Fill light (0 = black shadows). | | specularStrength | 0.75 | Specular strength. | | specularHardness | 22 | Specular hardness (higher = smaller highlight). | | relief | 1 | Exaggerates the normal map. | | lightZ | 1.4 | Light height (lower = grazing = more relief). | | lightRadius | 0.35 | Orbit radius. | | lightSpeed | 0.35 | Orbit speed (turns/sec). | | lightAngle | -0.7 | Fixed light angle (rad) when animateLight:false. | | lightColor | '#ffffff' | Light color. | | tint | null | Hex color multiplied over the base. | | opacity | 0.2 | Figure opacity. | | blendMode | 'normal' | Figure mix-blend-mode. | | brush | true | Paint the real background inside the silhouette. | | brushStrength | 24 | Smear strength (px). | | brushPosterize | 17 | Color levels per channel (paint patches). 0 = off. | | brushGrain | 0.1 | Canvas/bristle grain (0–1). | | brushUsesNormalMap | false | true = rigid glass-like refraction following the shape. | | shadow | null | Shadow texture PNG (aligned to the figure). | | shadowOpacity | 0.3 | Shadow opacity. | | shadowBlendMode | 'normal' | Shadow mix-blend-mode. |

Package layout

  • src/meccha-chameleon.mjs — native ESM (used by import / bundlers).
  • src/meccha-chameleon.js — CommonJS/UMD (used by require and CDN <script>).
  • src/presets/* — optional ready-made figures with embedded images, imported on demand via meccha-chameleon/presets/<name>.

Only src/ (plus README and LICENSE) is published; the playground itself is not part of the package.

Playground / config generator

playground/index.html is a visual editor: tune the sliders and it prints the exact MecchaChameleon.mount({...}) config for the current look, with a Copy button. Serve it over HTTP:

npm run playground
# or: npx http-server -c-1 -o playground/

The playground uses demo images under playground/assets/ (tracked in the repo, but excluded from the npm package). Drop your own image, normalMap and (optional) shadow PNGs there to try your own figure.

Browser support

brush uses backdrop-filter + SVG filters — solid in Chromium/Safari; the url() reference in backdrop-filter is weak in Firefox (the lit figure still works, the painted background may not).

License

MIT