| name | integrating-physics-animations |
| description | Adds physics-based flying objects using matter.js - shooting logos that fly diagonally, bounce off walls with spark effects, and accumulate in a physics pile at the bottom. Uses requestAnimationFrame with direct DOM manipulation for 60fps. Use when adding interactive physics animations to a web display. |
Integrating Physics Animations
Flying objects (conference logos) that soar across screen, bounce off walls, and pile up at the bottom using matter.js 2D physics.
Architecture
- requestAnimationFrame loop — bypasses React state for 60fps performance
- Direct DOM manipulation — create/modify DOM elements without React re-renders
- matter.js physics — handles pile accumulation and collisions at the bottom
- CSS for visual effects — tails, sparks, glows defined in shooting-stars.css
Component Structure
"use client";
import { useEffect, useRef } from "react";
import Matter from "matter-js";
export function ShootingStars() {
const containerRef = useRef<HTMLDivElement>(null);
useEffect(() => {
if (!containerRef.current) return;
return () => { };
}, []);
return <div ref={containerRef} className="shooting-stars-container" />;
}
Flying Object System
Spawning
Objects spawn every 10-20 seconds from either top or left edge:
- From top: fly diagonally downward-right
- From left: fly diagonally rightward-down
- Random velocity and angle within constrained ranges
Flight Path
Each flying object is a DOM element with:
- An inline SVG (conference logo)
- A glowing tail (CSS gradient pseudo-element)
- Position updated every frame via
requestAnimationFrame
star.x += star.vx;
star.y += star.vy;
star.el.style.transform = `translate(${star.x}px, ${star.y}px) rotate(${angle}deg)`;
Wall Bouncing
When a flying object hits a side wall:
- Reverse horizontal velocity (
vx = -vx)
- Spawn spark particles at impact point
- Continue flying
For patterns, see reference/matter-js-patterns.md.
Bottom Impact → Physics Pile
When a flying object hits the bottom:
- Remove the flying DOM element
- Create a matter.js body at impact position
- Render a static logo at the body's position
- Let physics handle pile accumulation
Pile Management
Cap at 50 logos in the pile. When exceeded, oldest fade out and are removed:
if (piledLogos.length > 50) {
const oldest = piledLogos.shift();
}
Golden Power-Ups
Logos that hit the bottom with high velocity glow gold and pulse:
.golden-logo {
filter: brightness(1.5) drop-shadow(0 0 8px #bbc446);
animation: golden-pulse 2s ease-in-out infinite;
}
CSS Structure (shooting-stars.css)
.shooting-stars-container {
position: fixed;
inset: 0;
z-index: 5;
pointer-events: none;
overflow: hidden;
}
.star-tail {
position: absolute;
width: 80px;
height: 3px;
background: linear-gradient(90deg, transparent, rgba(0, 192, 181, 0.6));
transform: rotate(var(--tail-angle));
}
.spark {
position: absolute;
width: 4px;
height: 4px;
border-radius: 50%;
background: #00c0b5;
}
Performance
- RAF loop: single
requestAnimationFrame drives all animations
- DOM pooling: reuse elements where possible
- Physics cap: max 50 bodies in pile
- No React state: all updates are direct DOM manipulation
- GPU hints:
will-change: transform on animated elements