The Rk4thSpring
class is a physics-based animation library that simulates a damped harmonic oscillator using the 4th-order Runge-Kutta method. It provides smooth and natural motion, ideal for UI animations, game development, or any application requiring realistic spring dynamics.
The Runge-Kutta 4th Order (RK4) method is a numerical technique for solving ordinary differential equations (ODEs) with high accuracy. In the context of spring animations, it offers a significant advantage over simpler methods like Euler's method by providing better stability and precision without greatly increasing computational cost. By using RK4, Rk4thSpring
can simulate complex spring dynamics accurately, resulting in smoother and more realistic animations that closely mimic natural motion.
- Physics-based spring animations using damped harmonic oscillator equations
- Configurable mass, tension, and friction parameters
- Built-in presets for common animation styles
- Event callbacks for animation lifecycle (start, update, end)
- High precision numerical integration using RK4 method
- Energy-based stopping condition for accurate animation completion
- TypeScript support with full type definitions
npm install rk4th-spring
import { Rk4thSpring } from 'rk4th-spring';
// Create a spring with default parameters
const spring = new Rk4thSpring();
// Animate to a target value
spring.start(100, (value) => {
// Update your UI with the current value
element.style.transform = `translateX(${value}px)`;
});
// Create a spring with a preset
const wobblySpring = Rk4thSpring.createWithPreset("wobbly", {
initialValue: 0,
onUpdate: (value) => {
element.style.scale = value;
},
});
// Start animation
wobblySpring.start(1);
const customSpring = new Rk4thSpring({
mass: 1, // Controls the "weight" of the animated object
tension: 170, // Controls the "stiffness" of the spring
friction: 26, // Controls the damping effect
precision: 0.01, // Controls when the animation stops
initialValue: 0, // Starting value
velocity: 0, // Initial velocity
targetValue: 0, // Initial target value
onStart: (value) => console.log("Animation started:", value),
onUpdate: (value) => console.log("Current value:", value),
onEnd: (value) => console.log("Animation completed:", value),
});
-
options
(Optional): An object containing configuration options.mass
(number): Mass of the object attached to the spring. Default is1
.tension
(number): Stiffness of the spring. Default is170
.friction
(number | null): Damping coefficient. Ifnull
, it's calculated as critical damping. Default isnull
.precision
(number): Energy threshold for stopping the animation. Default is0.01
.initialValue
(number): Initial position of the spring. Default is0
.velocity
(number): Initial velocity. Default is0
.targetValue
(number): Target position to animate towards. Default is0
.onStart
(Callback
| null): Function called when the animation starts.onUpdate
(Callback
| null): Function called on each animation frame.onEnd
(Callback
| null): Function called when the animation ends.
gentle
: Smooth, gentle animationswobbly
: Bouncy, playful animationsstiff
: Quick, responsive animationsslow
: Gradual, controlled animationsmolasses
: Heavy, slow-moving animationsavati
: Custom preset with high mass and friction
// Create an interactive button animation
const buttonSpring = Rk4thSpring.createWithPreset("wobbly", {
initialValue: 1,
onUpdate: (value) => {
button.style.transform = `scale(${value})`;
},
});
// Add interaction handlers
button.addEventListener("mousedown", () => {
buttonSpring.start(0.95); // Scale down on press
});
button.addEventListener("mouseup", () => {
buttonSpring.start(1); // Scale back to normal
});
const chainedAnimation = new Rk4thSpring({
tension: 180,
friction: 12,
onUpdate: (value) => {
// Animate multiple properties
element.style.transform = `
translateX(${value}px)
scale(${1 + value * 0.001})
`;
element.style.opacity = Math.min(1, value * 0.01);
},
onEnd: () => {
// Start next animation when this one completes
nextAnimation.start();
},
});
- Adjust Mass: Higher mass values create heavier-feeling animations
- Tune Tension: Higher tension values make the spring stiffer and faster
- Control Friction: Higher friction values reduce oscillation
- Use Precision: Adjust the precision value to control when animations stop
- Monitor Performance: Use the built-in callbacks to track animation progress
The Rk4thSpring
class employs the 4th-order Runge-Kutta method for numerical integration, providing high accuracy in simulating spring dynamics.
The acceleration a
is calculated using Hooke's law and damping force:
Animation stops when total mechanical energy falls below precision
.
-
Kinetic Energy:
$$KE = 0.5 \times \text{mass} \times \text{velocity}^2$$ -
Potential Energy:
$$PE = 0.5 \times \text{tension} \times (\text{position} - \text{targetValue})^2$$ -
Total Energy:
$$E_{\text{total}} = KE + PE$$
Relies on requestAnimationFrame
and performance.now()
. Compatible with modern browsers.
Contributions are welcome! Please open issues or submit pull requests on the GitHub repository.
This library is licensed under the MIT License.