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

canvas-js-3d

v1.0.1

Published

A lightweight, dependency-free 3D graphics library built on the HTML Canvas API and designed to run in web browsers.

Downloads

927

Readme

canvas-js-3d

npm version npm downloads license demo github

canvas-js-3d is a lightweight, dependency-free 3D graphics JavaScript library built on the HTML Canvas API and designed to run in web browsers. It makes it easy to load Wavefront OBJ files and render external 3D models directly to the canvas, without using WebGL, Three.js, or any other third-party libraries. The entire codebase is written in pure, vanilla JavaScript.

Great for learning, 3D web page visuals, small browser games (especially with synthwave/arcade visuals), and experimentation.

Demo

Demo Link: https://sebastianbathrick.github.io/canvas-js-3d/

IMAGE ALT TEXT HERE

Features

Rendering

  • Wireframe rendering (edges only)
  • Flat-shaded face colors (solid objects / non-wireframe)
  • Depth sorting (using painter's algorithm)
  • Back-face culling
  • Edge color gradients
  • Bloom
  • Distance‑based fog (rendered per-face)
  • Background color or vertical gradient
  • FPS counter

Scene & Math

  • Vector3 + Vector2 math
  • Transform with position/rotation/scale
  • Scene containing SceneObjects, each with their own mesh, material, & transform
  • Camera with adjustable FOV and transform

Assets

  • Wavefront OBJ loading (vertices + faces)
  • Load from URL, File, file dialog, or raw text

Quick Start

Installation

Install the canvas-js-3d package using the npm package manager. The npm package page is at this link: https://www.npmjs.com/package/canvas-js-3d.

npm install canvas-js-3d

index.html

<!DOCTYPE html>
<html>
    <head>
        <script type="importmap">
        {
            "imports": {
              "canvas-js-3d": "./node_modules/canvas-js-3d/src/index.js"
            }
        }
        </script>
    </head>
    <body>
      <canvas id="canvas" width="800" height="600"></canvas>
      <script type="module" src="app.js"></script>
    </body>
</html>

app.js

import { Engine, Mesh, SceneObject, Transform, Vector3, Material } from 'canvas-js-3d';

const canvas = document.getElementById('canvas');
const engine = new Engine(canvas);

// Define the geometry of a cube (or load a .obj file via WavefrontMeshConverter)
const vertices = [
    new Vector3(-1, -1, -1),  // 0: back-bottom-left
    new Vector3( 1, -1, -1),  // 1: back-bottom-right
    new Vector3( 1,  1, -1),  // 2: back-top-right
    new Vector3(-1,  1, -1),  // 3: back-top-left
    new Vector3(-1, -1,  1),  // 4: front-bottom-left
    new Vector3( 1, -1,  1),  // 5: front-bottom-right
    new Vector3( 1,  1,  1),  // 6: front-top-right
    new Vector3(-1,  1,  1)  // 7: front-top-left
];

const faces = [
    [1, 0, 3, 2],  // back
    [4, 5, 6, 7],  // front
    [0, 4, 7, 3],  // left
    [1, 2, 6, 5],  // right
    [3, 7, 6, 2],  // top
    [0, 1, 5, 4],  // bottom
];

const mesh = new Mesh(vertices, faces);

const cubeSceneObj = new SceneObject(
    mesh,
    new Transform(
        new Vector3(0, 0, 5), // Position
        Vector3.zero(), // Rotation (in radians)
        Vector3.one() // Scale
    ),
    new Material(
        '#ffffff', // Edge color
        null, // Optional gradient color (e.g. '#0000ff' for blue)
        '#333333' // Optional face color (null for wireframe)
    )
);

// Smoothly rotate the cube (gets called each frame)
engine.onFrameUpdate = (deltaTime) => {
    // deltaTime = time since last frame
    cubeSceneObj.transform.rotate(new Vector3(0, deltaTime, 0));
};

engine.scene.addSceneObject(cubeSceneObj);
engine.start();

Run a dev server:

npx http-server -c-1

This library uses native ES modules. You must run it from a local server (not file://).

Feature Usage

These snippets assume you already have an Engine, a SceneObject called cubeSceneObj, and a running render loop. They’re meant to be drop-in additions to the minimal setup above.

Depth Sorting (Solid Meshes)

engine.isDepthSorting = true; // Already enabled by default

Back-Face Culling

engine.camera.isBackFaceCulling = true; // Already enabled by default

Camera Transform

engine.camera.transform.setPosition(0, 0, -3);
engine.camera.transform.setRotation(0, 0, 0); // in radians

Camera Field of View (FOV)

engine.camera.setFov(90); // 90 degrees (60 degrees by default)

Background Color vs. Gradient

// Solid color
engine.backgroundColor = '#add8e6';
engine.backgroundGradientColor = null;

// Vertical gradient
engine.backgroundColor = '#000000';
engine.backgroundGradientColor = '#1a1a2e';

Default Edge Color (Fallback)

engine.defaultEdgeColor = '#00ff00';

Materials: Edges, Gradients, Faces

// Edges only
cubeSceneObj.material = new Material('#ffffff');

// Gradient edges
cubeSceneObj.material = new Material('#ff00ff', '#00ffff');

// Face fill (depth sorting must be enabled)
engine.isDepthSorting = true;

// Swap material before/after/during runtime
cubeSceneObj.material = new Material('#ff00ff', '#00ffff', '#222222');

Fog

engine.depthFog = {
    enabled: true,
    color: '#000000',
    near: 5,
    far: 40
};

Bloom

engine.bloom = {
    enabled: true,
    blur: 5,
    color: null // null = use edge color
};

FPS Counter

engine.isFrameRateCounter = true;
engine.debugTextColor = '#ffffff';

Screen Resize Handling

import { Vector2 } from 'canvas-js-3d';

engine.screenSize = new Vector2(
    500, // Width 500px
    500 // Height 500px
);

Loading an OBJ Mesh

import { WavefrontMeshConverter } from 'canvas-js-3d';

const mesh2 = await WavefrontMeshConverter.fromUrl('./model.obj');

const obj = new SceneObject(
    mesh2,
    new Transform(new Vector3(4, 0, 4), Vector3.zero(), Vector3.one()),
    new Material('#ffffff', null, '#222222')
);

engine.scene.addSceneObject(obj);

Supported File Sources:

  • WavefrontMeshConverter.fromUrl(url);
  • WavefrontMeshConverter.fromFile(file);
  • WavefrontMeshConverter.fromFileDialog();
  • WavefrontMeshConverter.fromText(objString);

Only vertex positions and face indices are parsed. Normals and UVs are ignored.

Stop Engine

engine.stop();

Directory Structure

src/
├─ math/              # Vectors & transform math
├─ core/              # Scene, mesh, engine, material, scene object
├─ rendering/         # Camera, renderer, post effects
└─ wavefront-loading/ # OBJ loader pipeline

License

MIT © 2026 Sebastian Bathrick