Lightweight, dependency-free SVG wave templates that generate a new path every time they render. Each wave is a standard custom element (<dynamo-wave>) that keeps its authored host in the DOM, renders an SVG inside it, and can morph or animate on demand.
- Drop-in custom element – include
<dynamo-wave>anywhere in your markup; classes, styles, and IDs flow through automatically. - Deterministic or generative – seed waves for reproducible shapes, or let them randomize and re-render via Intersection Observer triggers.
- Rich data attributes – configure direction, variance, anchoring, animation speed, observation behavior, and more without writing JS.
- Runtime controls – programmatic API (
generateNewWave,play,pause) with TypeScript definitions plus adynamo-wave-completeevent hook. - Animation aware – responds to live
prefers-reduced-motionchanges and cancels animation/observer work while detached.
npm install dynamowaves// Registers the <dynamo-wave> custom element globally
import 'dynamowaves';<!-- Local copy -->
<script src="/path/to/dynamowaves.js"></script>
<!-- jsDelivr CDN, pinned to the compatible 2.x line -->
<script src="https://cdn.jsdelivr.net/npm/dynamowaves@2/dist/dynamowaves.min.js" crossorigin="anonymous"></script>- Add the script to the
angular.jsonscriptsarray:"scripts": [ "node_modules/dynamowaves/dist/dynamowaves.js" ]
- Opt in to custom elements support:
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; @NgModule({ // ... schemas: [CUSTOM_ELEMENTS_SCHEMA] }) export class AppModule {}
<dynamo-wave class="fill-theme"></dynamo-wave>
<style>
.fill-theme { fill: var(--theme); }
</style>| Attribute | Default | Purpose |
|---|---|---|
data-wave-points |
6 |
Integer anchor count, clamped to 2–1000. |
data-wave-variance |
3 |
Finite point deviation, clamped to -100–100. |
data-variance |
unset | Legacy alias for data-wave-variance. |
data-wave-seed |
generated | Recorded Base64 path or plain deterministic seed. |
data-start-end-zero |
false | Anchors endpoints on the base edge. |
data-wave-face |
top |
Orientation of the wave. |
data-wave-speed |
7500 |
Positive loop duration in milliseconds. |
data-wave-animate |
false |
The exact string true enables automatic playback. |
data-wave-observe |
unset | once or repeat, with an optional root margin. |
Numeric bounds and lifecycle hardening described here were added in 2.2.1; see CHANGELOG.md.
All attributes are observed at runtime: changing one after render re-renders or reconfigures the wave immediately (a running loop resumes with the new settings).
<dynamo-wave id="hero-wave" data-wave-animate="true"></dynamo-wave>
<script>
const heroSeed = document.getElementById('hero-wave')?.getAttribute('data-wave-seed');
if (heroSeed) {
const footerWave = document.createElement('dynamo-wave');
footerWave.setAttribute('data-wave-seed', heroSeed);
document.body.appendChild(footerWave);
}
</script>import {
DynamoWave,
generateWave,
parsePath,
interpolateWave,
encodeWaveSeed,
decodeWaveSeed,
} from 'dynamowaves';ESM and CommonJS expose the same six names. Direct browser scripts expose them on globalThis.Dynamowaves.
| Instance method | Description |
|---|---|
generateNewWave(duration = 800) |
Morph once to a new random path. |
play(duration?) |
Start a continuous loop. |
pause() |
Stop a loop or cancel an active one-off morph. |
pause() stays authoritative across geometry, connection, and motion-preference changes. A later play() resumes a paused loop; detached playback requests schedule no frames until reconnection. Non-finite generateNewWave() durations use 800 ms.
dynamo-wave-complete fires after a one-off morph and after every completed loop cycle. Its detail is { duration, direction: 'horizontal' | 'vertical' }.
See src/lib/content/examples.md or the docs site.
- Generated SVGs are decorative and hidden from assistive technology.
- Continuous motion stops when reduced motion is enabled; new one-off morphs use one millisecond, and active morphs finish immediately.
- The module imports safely during SSR. Reuse a recorded seed when the first client-rendered shape must be identical.
git clone https://github.com/mzebley/dynamowaves.git
cd dynamowaves
npm install
npm run build
npm test
npx playwright install chromium
npm run test:browsernpm run build remains the publishable library build. The documentation is a
fully prerendered SvelteKit/mdsvex site that imports the local library source:
npm run dev:docs # local docs development
npm run build:docs # library, Zebkit, and prerendered docs
npm run check:docs # Svelte and Zebkit authored-markup checks
npm run preview:docs # preview the production docs build
npm run verify:docs # rendered Zebkit verification against the previewRun generated Zebkit steps serially: build before check, and restart the preview after the generated runtime or CSS changes.
ISC © Mark Zebley