glissix
v0.1.0
Published
An inertia-driven physics engine for tactile UI motion.
Downloads
170
Maintainers
Readme
Glissix
An inertia-driven, spring-damper physics engine for tactile UI motion. Focuses on physical simulation (momentum, weight, and drag) so that interface elements feel dragged, flicked, and released naturally, instead of executing rigid time-based bezier curves.
✦ Features
- Tactile Material Presets: Load physically pre-tuned configurations like
LEATHER,RUBBER,HONEY, andGHOST. - Dynamic Impulse Injection: Inject instantaneous speed at any time (
applyImpulse) to support fluid swipe-and-flick gestures. - Auto-Sanitized Physics: Automatic clamping limits for mass, tension, and friction to guarantee mathematical stability and prevent spring explosion or jitter.
- Framework Agnostic: Pure TypeScript library with zero dependencies. Runs seamlessly in React, Vue, Svelte, or vanilla JS/TS.
- Ultra-Lightweight: Only ~2.2KB gzipped.
✦ Core Physical Parameters
Unlike duration-based animators, Glissix uses a mathematical spring-mass-damper system:
mass(0.1 - 10.0): Represents the inertia of the moving element. A higher mass creates a feeling of weight, taking longer to accelerate and decelerate.tension(0.001 - 1.0): Represents the stiffness of the spring. High tension pulls the element toward the target aggressively, while lower tension feels loose.friction(0.01 - 0.999): Represents the damping or resistance. High friction dampens oscillation quickly (critical damping), while low friction lets the element bounce.
✦ Installation
npm install glissix✦ Quick Start
1. Basic 2D Position Tracking (e.g. Card Drag & Flick)
import { Glissix } from 'glissix';
// Instantiate with starting coordinates (0, 0)
const tracker = new Glissix(0, 0);
// Use a built-in tactile preset
tracker.useMaterial('LEATHER');
// Target a new coordinates (e.g., when the user releases a drag)
tracker.setTarget(300, 150);
// Inject an instantaneous speed (e.g. from pointer velocity tracker)
tracker.applyImpulse(25, -12);
// Physics animation loop
function animate() {
// Step computes the next physical coordinate based on delta forces
const { x, y, vx, vy } = tracker.step();
// Apply positions to CSS transform
card.style.transform = `translate3d(${x}px, ${y}px, 0)`;
// Keep animating until the element settles
const speed = tracker.getVelocity();
const distToTarget = Math.hypot(tracker.getState().targetX - x, tracker.getState().targetY - y);
if (speed > 0.001 || distToTarget > 0.01) {
requestAnimationFrame(animate);
}
}
animate();2. Animating 1D Values (e.g. Drawer Swipe-to-Open)
You can use the helper updateValue() to drive single variables like sheet positions, opacity, scale, or scroll offsets:
import { Glissix } from 'glissix';
const opacityTracker = new Glissix(0, 0); // initial value 0
opacityTracker.useMaterial('RUBBER');
function fadeOut() {
function tick() {
opacityTracker.updateValue(1.0, (val, speed) => {
overlay.style.opacity = val.toString();
});
if (Math.abs(opacityTracker.getState().x - 1.0) > 0.001) {
requestAnimationFrame(tick);
}
}
tick();
}✦ Presets & Materials
| Material Preset | Mass | Tension | Friction | Physical Feeling |
| :--- | :--- | :--- | :--- | :--- |
| LEATHER | 2.0 | 0.10 | 0.85 | Heavy, draggy, premium tactile dampening |
| RUBBER | 0.5 | 0.40 | 0.70 | Snappy, highly responsive, elastic spring |
| HONEY | 5.0 | 0.05 | 0.95 | Slow, high-viscosity, super smooth glide |
| GHOST | 0.1 | 0.20 | 0.99 | Float-like, almost frictionless motion |
✦ API Reference
Constructor
const tracker = new Glissix(initialX: number, initialY: number, config?: Partial<GlissixConfig>);Creates a new motion controller.
initialX: Initial position along the X axis.initialY: Initial position along the Y axis.config: Optional configuration object (values are automatically clamped):mass(defaults to1.0)tension(defaults to0.15)friction(defaults to0.82)
Instance Methods
setTarget(x: number, y: number): void
Sets the new destination coordinates.
applyImpulse(vx: number, vy: number): void
Injects an instantaneous impulse velocity (adds to current velocity). Perfect for throwing/flicking cards or lists.
step(): GlissixStep
Performs a single simulation step. Returns the current physics metrics:
{ x: number, y: number, vx: number, vy: number }
updateValue(target: number, callback: (value: number, velocity: number) => void): void
Steps a single scalar value. Sets target-x to target and returns the output via the callback.
useMaterial(name: GlissixMaterial): void
Loads a pre-tuned configuration ('LEATHER' | 'RUBBER' | 'HONEY' | 'GHOST').
setConfig(config: Partial<GlissixConfig>): void
Modifies the active configuration fields on-the-fly.
getVelocity(): number
Returns the scalar magnitude of the current velocity vector (speed).
getState(): GlissixState
Returns the exact physics simulation state copy:
{ x, y, vx, vy, targetX, targetY }
reset(x?: number, y?: number): void
Resets the position, target, and sets velocities to zero.
✦ Why Glissix?
Traditional transition tools require you to specify a preset curve (like ease-out) and duration. If a user flicks an element halfway through an animation, the motion snaps awkwardly.
Glissix solves this:
- Preserved Momentum: If a user drags and releases at speed, the swipe velocity is fed directly into the engine, producing a seamless decelerating slide.
- Dynamic Redirection: Changing targets mid-flight alters the acceleration vector smoothly, preventing sudden direction snaps.
- Pure Math: No browser timers or complex rendering context is required, making it incredibly lightweight and deterministic.
✦ Creator
Developed and maintained by Nilanshu Kumar Singh:
- LinkedIn: nilanshukumarsingh
- Twitter/X: @nilanshukumar81
✦ License
MIT
