🚨 Shai-Hulud Strikes Again:834 Packages Compromised.Technical Analysis →
Socket
Book a DemoInstallSign in
Socket

dom-physics

Package Overview
Dependencies
Maintainers
1
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

dom-physics

A simple, performant physics engine for DOM elements. Preserves DOM structure while enabling realistic physics simulation.

latest
Source
npmnpm
Version
0.1.7
Version published
Maintainers
1
Created
Source

DOM Physics Engine

A simple, performant physics engine for DOM elements. Preserves DOM structure while enabling realistic physics simulation. Built with TypeScript.

🌐 Live Demos on GitHub Pages | 📦 npm

Why This Package?

Simple & Fast

  • No complex nesting - Simple Body and World classes
  • Direct physics - No inheritance chains or recursive lookups
  • Optimized collision detection - Simple O(n²) for small counts, efficient for most use cases
  • Minimal overhead - Only manipulates CSS transform properties

What Changed from Complex Version?

The previous version had advanced features like:

  • World extending Body (nesting)
  • Physics inheritance with recursive lookups
  • SpatialHash optimization (removed - not needed for typical use cases)
  • Complex coordinate transformations

Why we simplified:

  • Performance - Recursive lookups (getEffectiveGravity(), getWorldPosition()) were called every frame, causing O(n) complexity
  • Simplicity - Most use cases don't need nesting - a simple World with Bodies is enough
  • Reliability - Fewer moving parts = fewer bugs
  • Maintainability - Easier to understand and modify

Result: The simplified version matches the original demo's performance exactly while being much easier to use and understand.

Features

✅ DOM Structure Preserved - Never modifies DOM hierarchy, only manipulates transforms
✅ Simple API - Just World and Body classes
✅ Framework Agnostic - Works with vanilla JS, React, Vue, etc.
✅ TypeScript - Full type safety and IntelliSense support
✅ Performant - Optimized for 60fps with many bodies

Installation

npm install dom-physics

Quick Start

import { World, Body } from 'dom-physics';

// Create a world
const container = document.getElementById('world');
const world = new World(container, {
  gravity: 400,
  friction: 0.97,
  restitution: 0.5
});

// Create a body
const element = document.querySelector('.my-element');
const body = new Body(element, world, {
  mass: 1,
  radius: 15,
  restitution: 0.8
});

// Register and start
world.registerBody(body);
world.start();

Demos

🌐 Try all demos live on GitHub Pages

Main Demo (Published Demo)

Text Demo (demo-text.html) - Interactive text that responds to mouse movement. This is the main published demo showcasing the package.

Additional Demos

  • Squares Demo (demo-squares.html) - Click to add squares, hover to push them around. Demonstrates collision detection and bounds.
  • Bouncing Balls (demo-bouncing.html) - Colorful balls bouncing in a circular container. Shows high restitution physics.
  • Stack Demo (demo-stack.html) - Build towers by clicking. Watch blocks stack and balance with realistic physics.

Running Demos Locally

Option 1: Using npm (if installed as package)

# Install the package
npm install dom-physics

# Navigate to package directory
cd node_modules/dom-physics

# Run the demo server
npm run demo:package

# Open http://localhost:8087/demo-package/ in your browser
# Navigate to specific demos:
# - http://localhost:8087/demo-package/demo-text.html (main demo)
# - http://localhost:8087/demo-package/demo-squares.html
# - http://localhost:8087/demo-package/demo-bouncing.html
# - http://localhost:8087/demo-package/demo-stack.html

Option 2: From Source (if developing)

# Clone the repository
git clone https://github.com/kai4avaya/dom-physics.git
cd dom-physics

# Install dependencies
npm install

# Build the package
npm run build

# Run the demo server
npm run demo:package

# Open http://localhost:8087/demo-package/ in your browser

Option 3: Original Inline Demo

# Run the original inline demo (for comparison)
npm run demo

# Open http://localhost:8087/ in your browser

API Reference

World

class World {
  constructor(container: HTMLElement, config?: WorldConfig)
  
  // Simulation control
  start(): void
  stop(): void
  
  // Body management
  registerBody(body: Body): void
  unregisterBody(body: Body): void
  
  // Properties
  container: HTMLElement
  bodies: Body[]
  gravity: number
  friction: number
  restitution: number
  timeStep: number
  bounds: { x: number; y: number; width: number; height: number }
}

Body

class Body {
  constructor(
    element: HTMLElement,
    world: World,
    config?: BodyConfig
  )
  
  // Physics control
  applyForce(fx: number, fy: number): void
  
  // Position queries
  getWorldPosition(): { x: number; y: number }
  
  // Rendering
  render(): void
  
  // Properties
  element: HTMLElement
  world: World
  x: number
  y: number
  mass: number
  radius: number
  restitution: number | null
  friction: number | null
  isStatic: boolean
  enabled: boolean
}

Configuration

WorldConfig

interface WorldConfig {
  gravity?: number;        // px/s² (default: 980)
  friction?: number;       // 0-1 (default: 0.99)
  restitution?: number;    // 0-1 (default: 0.8)
  bounds?: {               // Default: auto-detect from container
    x: number;
    y: number;
    width: number;
    height: number;
  };
  timeStep?: number;       // seconds (default: 1/60)
}

BodyConfig

interface BodyConfig {
  mass?: number;           // Default: 1
  radius?: number;          // Default: auto-calculated from element size
  restitution?: number | null;  // null = use world's restitution
  friction?: number | null;     // null = use world's friction
  isStatic?: boolean;      // Default: false
}

Examples

Basic Usage

const world = new World(container, {
  gravity: 400,
  friction: 0.97,
  restitution: 0.5
});

const body = new Body(element, world, {
  mass: 1,
  radius: 15
});

world.registerBody(body);
world.start();

Mouse Interaction

container.addEventListener('mousemove', (e) => {
  const rect = container.getBoundingClientRect();
  const mx = e.clientX - rect.left;
  const my = e.clientY - rect.top;
  
  world.bodies.forEach(body => {
    const pos = body.getWorldPosition();
    const dx = pos.x - mx;
    const dy = pos.y - my;
    const dist = Math.sqrt(dx * dx + dy * dy);
    
    if (dist < 100 && dist > 0) {
      const force = (100 - dist) * 2;
      body.applyForce(
        (dx / dist) * force,
        (dy / dist) * force
      );
    }
  });
});

Custom Physics Properties

// Body uses world's friction and restitution
const body1 = new Body(element1, world);

// Body overrides restitution
const body2 = new Body(element2, world, {
  restitution: 0.9  // Bouncier than world default
});

// Body overrides friction
const body3 = new Body(element3, world, {
  friction: 0.95  // Less friction than world default
});

Principles

  • DOM Structure Preserved - Never modifies DOM hierarchy
  • Transform Only - Only manipulates transform CSS property
  • World Space Simulation - Bodies simulate in world space, render relative to DOM
  • Simple & Fast - No unnecessary complexity

Testing

npm test              # Run tests in watch mode
npm run test:run      # Run tests once
npm run test:coverage # Run tests with coverage

License

MIT

Keywords

physics

FAQs

Package last updated on 11 Nov 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts