Appearance
Dynamics.applyExplosion()
Applies a sudden outward radial velocity impulse to a group of elements, simulating an explosion or blast wave. The engine computes per-element trajectories from a central origin point, integrates gravity and air resistance each frame, and bounces elements off a configurable floor with restitution. Returns an instance with a kill() method to halt the simulation.
Click to re-detonate.
1. Basic Radial Burst
When no originX / originY is provided, the engine derives the epicenter from the geometric center of all targeted elements' bounding boxes. Each element receives a randomized outward velocity scaled by force and forceVariation, with gravity and floor bounce applied each frame.
Click to detonate.
js
import { applyExplosion } from 'animx/plugins/Dynamics';
applyExplosion('.fragment', {
force: 1500,
gravity: 1200,
bounds: '#stage', // confines all four walls to the container
restitution: 0.6, // 60% energy retained per bounce
spin: 720, // up to 720° of random rotation per element
decay: 0.96 // air resistance per frame
})2. Custom Epicenter
originX and originY accept explicit viewport-space coordinates, overriding the auto-computed center. Binding these to a pointer event directs the impulse away from the exact click or touch position, enabling aimed or interactive explosions.
Click anywhere to aim the blast epicenter.
js
canvas.addEventListener('click', (e) => {
applyExplosion('.fragment', {
force: 1400,
gravity: 1000,
bounds: '#stage',
spin: 600,
originX: e.clientX, // viewport-space X of the blast epicenter
originY: e.clientY // viewport-space Y of the blast epicenter
});
}, { once: true }); // fire only on the first click3. Blast Radius Confinement
The radius property defines a circular blast zone around the origin. Elements whose center lies beyond this distance receive zero impulse and remain stationary. This enables localized detonations within a larger field of elements - such as proximity explosions or zone-of-effect mechanics.
Click to fire - only elements inside the ring are blasted.
radius: 60px
js
applyExplosion('.fragment', {
force: 1400,
gravity: 1100,
bounds: '#stage',
spin: 450,
radius: 60 // Elements farther than 60px from the origin receive no impulse
})4. Zero-Gravity Shockwave
Setting gravity: 0 eliminates the downward pull entirely. Elements drift outward along their initial trajectory, decelerating only by decay (air resistance). With decay close to 1.0, elements travel long distances before halting - applicable to space, underwater, or slow-motion dissipation effects.
Click to scatter - elements drift in zero gravity.
js
applyExplosion('.fragment', {
force: 480,
decay: 0.993, // Near-zero air resistance - elements drift freely
gravity: 0, // No gravitational pull
spin: 180
})
// Fade elements as they drift out of view
animate('.fragment', { duration: 4, delay: 0.8, opacity: 0, ease: 'quad.in' })5. High-Bounce Confetti
A restitution value near 1.0 produces near-perfectly elastic collisions with the floor. Combined with a high spin and tight floor constraint, elements ricochet chaotically before settling - effective for celebration bursts, card flick animations, or particle-field effects.
Click to burst the confetti.
js
applyExplosion('.confetti', {
force: 700,
forceVariation: 0.7, // High variance - each piece travels a different distance
gravity: 1600,
floor: 260,
restitution: 0.88, // 88% energy preserved per bounce - highly elastic
spin: 1080, // Up to 3 full rotations per piece
decay: 0.97
})6. Chain Reaction
timeline().call() schedules physics callbacks at precise time offsets without requiring native timers. Each call fires independently against a distinct element group, producing a staggered multi-cluster detonation with escalating force values.
Click to trigger the chain reaction.
js
import { timeline } from 'animx';
import { applyExplosion } from 'animx/plugins/Dynamics';
const tl = timeline();
// Each call() fires at a specific time offset (seconds)
<LivePreview :code="demoCode7" :height="380" hint="Click - gravity pulls rightward instead of down.">
<template #stage>
<div style="position:absolute;inset:0;background:#0f172a;cursor:pointer;">
<div class="dir-block" style="position:absolute;left:calc(38% - 56px);top:calc(50% - 56px);width:32px;height:32px;background:#818cf8;border-radius:50%;box-shadow:0 0 16px rgba(129,140,248,0.7);"></div>
<div class="dir-block" style="position:absolute;left:calc(38% - 16px);top:calc(50% - 56px);width:32px;height:32px;background:#c084fc;border-radius:50%;box-shadow:0 0 16px rgba(192,132,252,0.7);"></div>
<div class="dir-block" style="position:absolute;left:calc(38% + 24px);top:calc(50% - 56px);width:32px;height:32px;background:#f472b6;border-radius:50%;box-shadow:0 0 16px rgba(244,114,182,0.7);"></div>
<div class="dir-block" style="position:absolute;left:calc(38% - 56px);top:calc(50% - 16px);width:32px;height:32px;background:#38bdf8;border-radius:50%;box-shadow:0 0 16px rgba(56,189,248,0.7);"></div>
<div class="dir-block" style="position:absolute;left:calc(38% - 16px);top:calc(50% - 16px);width:32px;height:32px;background:#a78bfa;border-radius:50%;box-shadow:0 0 16px rgba(167,139,250,0.7);"></div>
<div class="dir-block" style="position:absolute;left:calc(38% + 24px);top:calc(50% - 16px);width:32px;height:32px;background:#fb923c;border-radius:50%;box-shadow:0 0 16px rgba(251,146,60,0.7);"></div>
<div class="dir-block" style="position:absolute;left:calc(38% - 56px);top:calc(50% + 24px);width:32px;height:32px;background:#4ade80;border-radius:50%;box-shadow:0 0 16px rgba(74,222,128,0.7);"></div>
<div class="dir-block" style="position:absolute;left:calc(38% - 16px);top:calc(50% + 24px);width:32px;height:32px;background:#60a5fa;border-radius:50%;box-shadow:0 0 16px rgba(96,165,250,0.7);"></div>
<div class="dir-block" style="position:absolute;left:calc(38% + 24px);top:calc(50% + 24px);width:32px;height:32px;background:#f43f5e;border-radius:50%;box-shadow:0 0 16px rgba(244,63,94,0.7);"></div>
<div style="position:absolute;bottom:12px;right:14px;font-size:11px;color:rgba(255,255,255,0.22);pointer-events:none;">gravity ?</div>
</div>
</template>
</LivePreview>
```js
applyExplosion('.fragment', {
force: 1200,
gravity: 900,
direction: 'x', // pulls elements rightward instead of downward
bounds: '#stage',
restitution: 0.55,
spin: 540
})8. Gravity Angle
gravityAngle sets the exact pull direction in degrees. 90 = down (default), 0 = right, 180 = left, 270 = up. Any angle in between produces a diagonal pull. Drag the slider to pick an angle - the compass needle shows the live gravity direction - then click the stage to detonate.
Set angle with the slider, then click to detonate.
gravityAngle: 90°
0°360°
js
const slider = document.querySelector('#ga-slider')
slider.addEventListener('input', () => {
const deg = +slider.value
document.querySelector('#ga-arrow').style.transform = `rotate(${deg - 90}deg)`
document.querySelector('#ga-label').textContent = `gravityAngle: ${deg}°`
})
canvas.onclick = (e) => {
if (e.target.closest('#ga-slider-wrap')) return
applyExplosion('.fragment', {
force: 1200,
gravity: 1000,
gravityAngle: +slider.value, // 90 = down, 0 = right, 180 = left, 270 = up
bounds: '#stage',
restitution: 0.55,
spin: 480
})
}API Reference
| Property | Type | Default | Description |
|---|---|---|---|
force | number | 1000 | Base outward velocity applied to each element at the moment of detonation. |
forceVariation | number | 0.2 | Randomizes the applied force per element. 0.2 means ±20% variance from force. |
decay | number | 0.95 | Air resistance multiplier applied each frame. Values closer to 1.0 result in longer flight distances. |
gravity | number | 0 | Downward acceleration (px/s²) applied after detonation. 0 disables gravitational pull. |
direction | 'y' | 'x' | 'y' | Gravity pull axis. 'y' pulls downward, 'x' pulls rightward. Overridden by gravityAngle. |
gravityAngle | number | 90 | Direction of gravity in degrees. 90 = down, 0 = right, 180 = left, 270 = up. Overrides direction. |
floor | number | Infinity | Y-offset (px) below the element's initial position at which bounce collisions are detected. |
restitution | number | 0.5 | Fraction of vertical velocity preserved per floor bounce. 0 is fully inelastic; 1 is perfectly elastic. |
spin | number | 360 | Maximum random rotational velocity (degrees) applied to each element. |
radius | number | Infinity | Blast zone radius (px). Elements whose center exceeds this distance from the origin are unaffected. |
originX / originY | number | (computed) | Viewport-space coordinates of the blast epicenter. Defaults to the bounding-box center of all targets. |
bounds | Element | undefined | A container element whose edges define hard collision walls on all four sides. |
onUpdate | function | - | Called each frame with the particles array. Each particle exposes el, x, y, vx, vy, active. |
Returned Instance
| Method | Description |
|---|---|
kill() | Immediately halts the physics simulation and unregisters the frame callback. |