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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@downpourdigital/physics

v2.0.1

Published

Animation physics!

Downloads

93

Readme

@downpourdigital/physics

npm bundle size

Spring physics for (UI-) animation!

Installation

yarn add @downpourdigital/physics
npm i --save @downpourdigital/physics

All multi-dimensional versions of the springs depend on gl-matrix, which you'll have to install manually.

Usage

import {
	EulerSpring,
	RK4Spring,
	LinearMotion,
	Passthrough,
  defaultWorld,
} from "@downpourdigital/physics";

import {
	EulerSpring2D,
	EulerSpring3D,
	EulerSpringQuat,
	RK4Spring2D,
	RK4Spring3D,	
	RK4SpringQuat,		
} from "@downpourdigital/physics/multi";


const loop = () => {
	defaultWorld.step( performance.now() );
	requestAnimationFrame( loop );
};

requestAnimationFrame( loop );

Simulation Variants

Springs are available as 1D, 2D, 3D, and quaternion versions, as well as with two different integrators.

  • EulerSprings are integrated via the semi-implicit Euler method. They are cheap to compute and probably good enough for most applications.

  • RK4Springs are integrated via the Runge–Kutta fourth order method. While computation-heavy, they are more accurate and may also be more stable under certain conditions.

Timestep

All simulations use a semi-fixed timestep internally. While the actual calculation is tied to the framerate, you can specify a maximum duration per simulation timestep (maxTimestep). If the interval between frames is higher than the max duration, it will be divided into multiple simulation timesteps. The amount of 'substeps' can be limited via maxStepCount.

Decreasing maxTimestep generally yields higher accuracy.

Example

import {
	RK4Spring,
} from "@downpourdigital/physics";

const spring = new RK4Spring({
	maxTimestep: 17, // in ms (default: 17)
	maxStepCount: 8, // (default: 8)
});

Springs

Config

A spring represents a mass-spring-damper system. It accepts the following options:

  • mass mass in kg (default: 1)
  • stiffness usually 1-500 (default: 250) Higher values cause the spring to be stiffer. (spring constant k from Hooke's Law)
  • damping usually 1-100 (default: 15) Higher values reduce oscillations more. (damping coefficient b)
  • value initial position (default: 0)
  • velocity initial velocity (default: 0)
  • restDelta the minimum speed (velocity magnitude) after which the system is considered resting. (default: .0001)

Example

import {
	RK4Spring,
} from "@downpourdigital/physics";

const spring = new RK4Spring({
	mass: 1,
	stiffness: 250,
	damping: 15,
});

Props and Methods

  • isResting: boolean

    Indicates wether the simulation is in a resting state or actively changing.

  • set( value: number ): void

    Sets the spring target to a given position. The spring will subsequently begin moving towards that position.

  • get(): number

    Returns the current spring position.

  • getVelocity(): number

    Returns the current velocity.

  • reset(): void

    Resets the spring to its initial position and to zero velocity.

  • resetTo( value: number ): void

    Resets the spring to a given position and to zero velocity.

  • stop(): void

    Ends the simulation.

2D, 3D and quaternion specific methods

  • set( value: vec2 | vec3 | quat ): void and resetTo( value: vec2 | vec3 | quat ): void

    set and resetTo expect the value to be a gl-matrix vec2/vec3/quat on the 2D, 3D and quat versions respectively.

  • get( out: vec2 | vec3 | quat ): void and getVelocity( out: vec2 | vec3 | quat ): void

    Similarly to gl-matrix functions, get and getVelocity don't return the position but rather expect an out vector to write the result to. This allows for better optimisation.

  • read(): vec2 | vec3 | quat and readVelocity(): vec2 | vec3 | quat

    read and readVelocity return the internal vector representation of position and velocity respectively.
    As they are being used internally, they should only be read. Mutating them will mess up the simulation. Also their values will change as the simulation runs.

Passthrough

Passthrough is a drop-in replacement for any 1D spring. As the name suggests, it just passes through the target value unaltered.

LinearMotion

LinearMotion represents a uniform linear motion with constant velocity/zero acceleration. It moves towards a given target at a given constant speed.

The API surface is the same as with other 1D springs.

Example

import {
	LinearMotion,
} from "@downpourdigital/physics";

const spring = new LinearMotion({
	value: 0, // initial position (default: 0)
	speed: 1, // speed in units per second (default: 1)
});

Manual stepping

Stepping can also be done manually: if autoStep: false is passed in the config of any simulation, it won't be attached to the default physics world. You can now step each simulation individually or bundle multiple simulations together in another physics world.

Example

import {
	World,
	EulerSpring,
} from "@downpourdigital/physics";

const spring = new EulerSpring({
	autoStep: false,
});

// either step individually
spring.step( time );

// or bundle in a world
const world = new World();
world.add( spring );

world.step( time );

Usage with @downpourdigital/scheduler

import { loop, update } from '@downpourdigital/scheduler';
import { defaultWorld } from '@downpourdigital/physics';

loop( () => [update( ( delta, time ) => defaultWorld.step( time ) )]);

License

© 2021 DOWNPOUR DIGITAL, licensed under BSD-4-Clause