UI Animations & Motion Design
Transform static web applications into living, tactile user interfaces through vector physics, smooth render loops, interactive pointer tracking, and real-time canvas graphics.
Introduction to Interactive Web Experiences
Interactive web interfaces bridge code and real-world intuition. Adding subtle physical responses—like weight, inertia, elastic movement, and springiness—makes applications feel responsive and modern.
// Example: Adding fluid hover physics class
element.classList.add('physics-hover');
Mouse Events & Pointer Tracking
Capture cursor position in real time using mousemove or pointermove to direct UI element orientations or particle targets.
const mouse = { x: 0, y: 0 };
window.addEventListener('pointermove', (e) => {
mouse.x = e.clientX;
mouse.y = e.clientY;
});
Collision Detection Basics
Detect when two objects intersect on screen using Axis-Aligned Bounding Box (AABB) or Euclidean Distance for circular elements.
// Circle collision distance check
function checkCollision(c1, c2) {
const dx = c1.x - c2.x;
const dy = c1.y - c2.y;
const distance = Math.hypot(dx, dy);
return distance < (c1.radius + c2.radius);
}
Gravity Simulation
Simulate downward environmental forces by continuously adding a constant gravitational acceleration to vertical velocity (vy).
const gravity = 0.5;
function applyGravity(object) {
object.vy += gravity; // Gravity accelerates downward speed
object.y += object.vy; // Update position
}
Velocity & Acceleration
Velocity dictates movement speed and direction, while acceleration dictates changes in velocity over time.
let x = 0, vx = 2, ax = 0.1;
function updateMotion() {
vx += ax; // Acceleration updates velocity
x += vx; // Velocity updates position
}
Friction & Bounce Effects
Simulate energy loss when objects bounce off screen borders or slide across surfaces by multiplying velocity by a restitution coefficient (< 1.0).
const bounce = -0.8; // Lose 20% energy on bounce
const friction = 0.98; // Air resistance / friction coefficient
if (y + radius >= floorY) {
y = floorY - radius;
vy *= bounce; // Invert and dampen vertical speed
vx *= friction; // Apply surface friction
}
Drag and Drop Mechanics
Implement smooth drag & drop by storing pointer offset on pointerdown, updating position on pointermove, and releasing on pointerup.
let isDragging = false, offset = { x: 0, y: 0 };
box.addEventListener('pointerdown', (e) => {
isDragging = true;
offset.x = e.clientX - box.offsetLeft;
offset.y = e.clientY - box.offsetTop;
});
window.addEventListener('pointermove', (e) => {
if (!isDragging) return;
box.style.left = `${e.clientX - offset.x}px`;
box.style.top = `${e.clientY - offset.y}px`;
});
window.addEventListener('pointerup', () => isDragging = false);
requestAnimationFrame() Animation Loop
requestAnimationFrame syncs animation updates directly with the monitor's refresh rate (~60-144fps) for butter-smooth rendering.
function animate() {
// 1. Clear frame / update state
updatePhysics();
// 2. Render frame
render();
// 3. Request next frame
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
Canvas vs DOM Animations
DOM CSS transforms excel for fewer (< 50) interactive UI components. HTML5 <canvas> excels for rendering thousands of high-performance physics particles simultaneously.
// Canvas render clear & draw
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI * 2);
ctx.fill();
Particle Effects
Spawn clusters of short-lived physical shapes with random initial velocities, colors, and shrinking opacity for spark, smoke, or firework visuals.
function createSpark(x, y) {
return {
x, y,
vx: (Math.random() - 0.5) * 8,
vy: (Math.random() - 0.5) * 8,
life: 1.0
};
}
Object-Oriented JavaScript for Physics Objects
Encapsulate physical properties (position, velocity, radius, mass) and movement methods inside clean JavaScript classes.
class PhysicsBall {
constructor(x, y, radius) {
this.x = x;
this.y = y;
this.radius = radius;
this.vx = (Math.random() - 0.5) * 4;
this.vy = 0;
}
update(gravity = 0.5) {
this.vy += gravity;
this.y += this.vy;
this.x += this.vx;
}
}
Performance Optimization
Optimize frame rates by using transform: translate3d() to leverage GPU acceleration, object pooling to prevent garbage collection pauses, and offscreen canvas buffers.
// GPU-accelerated DOM movement
el.style.transform = `translate3d(${x}px, ${y}px, 0)`;
Building a Google Gravity Clone (Step-by-Step)
Turn UI layout elements into rigid body physics objects that drop, collide, and roll across the bottom of the viewport upon interaction.
function applyGoogleGravity(elements) {
elements.forEach(el => {
el.style.position = 'absolute';
// Apply physics loop to el.style.top & el.style.left
});
}
Building Floating Buttons
Create floating Action Buttons (FAB) that gently bob using sinusoidal wave calculations: y = base + Math.sin(time) * amplitude.
let time = 0;
function floatButton(btn) {
time += 0.05;
const offsetY = Math.sin(time) * 12; // 12px floating range
btn.style.transform = `translateY(${offsetY}px)`;
}
Exploding Text Effects
Split heading text into individual <span> letter nodes and burst them outwards into particles upon mouse click.
const letterSpan = document.createElement('span');
letterSpan.textContent = 'A';
// Apply radial blast velocity (vx, vy) on click event
Magnetic Cursor Effect
Attract nearby UI buttons toward the cursor when the pointer comes within a proximity threshold.
const distance = Math.hypot(mouseX - btnX, mouseY - btnY);
if (distance < 100) { // Magnetic radius
btn.style.transform = `translate(${(mouseX - btnX) * 0.3}px, ${(mouseY - btnY) * 0.3}px)`;
}
Falling Cards Animation
Cascade UI card elements sequentially with staggered drop delays and subtle 3D rotational tilt.
cards.forEach((card, index) => {
setTimeout(() => {
card.classList.add('falling-active');
}, index * 150); // Staggered cascade delay
});
Interactive Landing Page Motion
Combine parallax scroll tracking, floating dynamic background shapes, and cursor magnetic forces into a cohesive motion design system.
window.addEventListener('scroll', () => {
const scrolled = window.scrollY;
heroBg.style.transform = `translateY(${scrolled * 0.4}px)`;
});
The Mini Challenge: Vector Physics Engine
Implement a class PhysicsParticle that constructs a particle at (x, y) with initial velocities (vx, vy) and an update(gravity, bounce) method:
- Accelerates vertical velocity by
gravity:vy += gravity. - Updates position:
x += vxandy += vy. - Returns an object with updated
{ x, y, vx, vy }.