Try now on dotwave.jsem-nerad.cz
- Parallax effect for depth perception
- Fully customizable (colors, sizes, behavior...)
- Custom dot shapes (squares, triangles, stars, your own images or draw functions)
- Color palettes - dots pick random colors from a list you define
- Motion presets - dots can flow in a stream or swirl in a vortex on their own
- Dot stretching
- Dot rotation smoothing
- No dependencies
- Lightweight (~8kB minified)
The recommended way to import DotWave is via the remote like this:
<script src="https://dotwave.jsem-nerad.cz/src/dotwave.min.js"></script>Or You can also download it and include it in Your HTML:
<script src="/path/to/dotwave.min.js"></script>For modifying the library itself, download the non-minified version.
To use DotWave as a HTML element, you will first need to additionally import the dotwave-element.min.js extension for the core dotwave library:
<script src="https://dotwave.jsem-nerad.cz/src/dotwave.min.js"></script>
<script src="https://dotwave.jsem-nerad.cz/src/dotwave-element.min.js"></script> <!-- extension library -->Then you can use the DotWave element simply like this:
<!-- This code example creates a basic DotWave canvas with the default options -->
<dot-wave></dot-wave>The DotWave element can be used and customised as every other HTML element. You can use it and style it as as a container for other HTML elements.
/* Styling in CSS */
dot-wave {
display: flex;
align-items: center;
justify-content: center;
}<!-- Styling directly in the element style -->
<dot-wave style="width: 600px; height: 400px; border: 3px solid #33a6ed;">
<!-- Using as a container for paragraph element -->
<p style="color: #33a6ed;">This is DotWave element as a container with custom CSS.</p>
</dot-wave>To configure the DotWave element, use the element attributes.
<dot-wave
num-dots="200"
dot-color="#FF0000"
background-color="#FFFFFF"
influence-radius="150"
dot-stretch="true"
dot-stretch-mult="5"
style="height: 500px;">
</dot-wave>You can find the list of all available attributes here.
In addition to the HTML element, you can still control the DotWave object using JavaScript including using functions and updating options
// Get reference to the element
const dotWaveElement = document.querySelector('dot-wave');
// Update properties via JavaScript
dotWaveElement.numDots = 500;
dotWaveElement.dotColor = '#00FF00';
dotWaveElement.reactive = false;
// Control animation
dotWaveElement.pause();
dotWaveElement.resume();
// Access the underlying DotWave instance for advanced control
const dotwave = dotWaveElement.getDotWaveInstance();
if (dotwave) {
// Use any original DotWave methods
dotwave.updateOptions({ friction: 0.95 });
}
// Clean up when done
dotWaveElement.destroy();The DotWave element also supports dynamic creation in JavaScript
// Create element dynamically
const dotWave = document.createElement('dot-wave');
dotWave.setAttribute('num-dots', '300');
dotWave.setAttribute('dot-color', '#FF00FF');
dotWave.style.width = '100%';
dotWave.style.height = '500px';
document.body.appendChild(dotWave);<div id="dotwave-container" style="height: 400px;"></div>
<script src="https://dotwave.jsem-nerad.cz/src/dotwave.min.js"></script>
<script>
// Creating a new DotWave instance with custom configuration
const dotwave = new DotWave({container: '#dotwave-container'});
</script>If you want to put your script tags at the top of Your HTML with the defer property, make sure to also do the same to the script containing the DotWave customization, otherwise it won't work.
To configure DotWave when initializing, use the class options.
<script>
// Creating a new DotWave instance with custom configuration
const dotwave = new DotWave({
container: '#dotwave-container',
numDots: 200,
dotColor: '#FF0000',
backgroundColor: '#FFFFFF',
influenceRadius: 150,
dotStretch: true,
dotStretchMult: 5,
});
</script>You can find the list of all available attributes here.
By default, DotWave draws circles. Use the dotShape option (or the dot-shape attribute) to change that:
| Value | Result |
|---|---|
"circle" |
The classic dot (default) |
"square" |
Square dots |
"triangle" |
Triangle dots that point in the direction of travel when stretched |
"star" |
Five-pointed stars |
"image" |
Draws the image from the dotImage option instead of a shape |
// Star-shaped dots
const dotwave = new DotWave({
dotShape: 'star',
dotMinSize: 2,
dotMaxSize: 6,
});
// Image dots (e.g. snowflakes, logos, sprites...)
const snow = new DotWave({
dotShape: 'image',
dotImage: '/images/snowflake.png',
dotMinSize: 4,
dotMaxSize: 10,
});<dot-wave dot-shape="triangle"></dot-wave>
<dot-wave dot-shape="image" dot-image="/images/snowflake.png" dot-min-size="4" dot-max-size="10"></dot-wave>Some notes on shapes and images:
- All built-in shapes support dot stretching - they rotate towards their direction of travel and stretch along it, just like circles do.
- Images keep their aspect ratio and are scaled so their larger side matches the dot diameter. Since the default dot sizes (1-3) are quite small, you will usually want to increase
dotMinSize/dotMaxSizefor image dots. - While the image is loading (or if it fails to load), dots are drawn as regular circles, so the canvas never appears empty.
- Dot colors do not apply to images - the image keeps its own colors. Per-dot opacity still applies.
For full control, dotShape also accepts a function that traces a path centered at (0, 0). DotWave handles position, rotation, stretching and filling for you:
const dotwave = new DotWave({
// A simple diamond shape
dotShape: function(ctx, radius) {
ctx.moveTo(0, -radius);
ctx.lineTo(radius, 0);
ctx.lineTo(0, radius);
ctx.lineTo(-radius, 0);
ctx.closePath();
},
});Instead of a single dotColor, you can pass an array of colors with dotColors. Each dot picks one color from the palette at random when it is created:
const dotwave = new DotWave({
dotColors: ['#33a6ed', '#ed33a6', 'gold', 'rgb(166, 237, 51)'],
});For the HTML element, use a comma-separated list:
<dot-wave dot-colors="#33a6ed, #ed33a6, gold"></dot-wave>When dotColors is set (and not empty), it takes precedence over dotColor. Updating dotColor or dotColors via updateOptions() re-rolls the colors of all existing dots without resetting their positions. All CSS color formats supported by dotColor (named, hex, RGB/RGBA) work in the palette too.
By default, dots just wander randomly (and react to your cursor). The motion option gives them a direction of their own:
| Value | Result |
|---|---|
"none" |
Classic random wandering (default) |
"stream" |
Dots constantly flow in one direction, like a river or snowfall |
"vortex" |
Dots swirl around a configurable center point |
// A stream flowing to the bottom-right
const stream = new DotWave({
motion: 'stream',
motionAngle: 45, // Direction in degrees: 0 = right, 90 = down, 180 = left, 270 = up
motionStrength: 0.1, // How strong the flow is
});
// A vortex swirling around the center
const vortex = new DotWave({
motion: 'vortex',
motionStrength: 0.15,
motionCenterX: 0.5, // Center as a fraction of the canvas size (0-1)
motionCenterY: 0.5,
});<dot-wave motion="stream" motion-angle="270" motion-strength="0.08"></dot-wave>
<dot-wave motion="vortex" motion-strength="0.15"></dot-wave>Notes on motion presets:
- Motion presets combine with everything else: cursor reactivity, random movement, friction and
maxSpeedall still apply. For a perfectly uniform stream, setrandomFactor: 0. motionStrengthis a continuous force, so its visible speed is balanced againstfrictionand capped bymaxSpeed.- For
vortex, a negativemotionStrengthreverses the spin direction. - The vortex center is relative to the canvas size, so
0.5/0.5always stays in the middle, even after resizing. Values outside0-1place the center off-canvas, which works too.
// Initialize
const dotwave = new DotWave(options);
// Pause animation
dotwave.pause();
// Resume animation
dotwave.resume();
// Update options
dotwave.updateOptions({
dotColor: 'blue',
numDots: 300
});
// Clean up when done
dotwave.destroy();| HTML Attribute | JavaScript option | Type | Default | Description |
|---|---|---|---|---|
| - | container | string | body | Container selector or DOM element |
| num-dots | numDots | number | 400 | Total number of dots rendered |
| dot-color | dotColor | string | "white" | Dot color; supports named, hex, RGB/RGBa CSS color values |
| background-color | backgroundColor | string | "black" | Canvas fill color; use "transparent" to disable fill |
| dot-min-size | dotMinSize | number | 1 | Minimum dot radius |
| dot-max-size | dotMaxSize | number | 3 | Maximum dot radius |
| dot-min-opacity | dotMinOpacity | number | 0.5 | Minimum dot opacity at far depth for fade effect |
| dot-max-opacity | dotMaxOpacity | number | 1 | Maximum dot opacity at near depth for vivid foreground |
| influence-radius | influenceRadius | number | 100 | Cursor effect radius in pixels for interactive push/pull |
| influence-strength | influenceStrength | number | 0.5 | Multiplier for cursor velocity influence on dots |
| random-factor | randomFactor | number | 0.05 | Random dot movement factor |
| friction | friction | number | 0.97 | Dot movement friction to slow dots down |
| max-speed | maxSpeed | number | 3 | Clamp for dot speed after all influences |
| reactive | reactive | boolean | true | Enables/disables cursor reactivity entirely |
| z-index | zIndex | number | -1 | Canvas z-index |
| mouse-speed-decay | mouseSpeedDecay | number | 0.85 | How quickly mouse speed decays |
| max-mouse-speed | maxMouseSpeed | number | 15 | Caps cursor velocity to avoid spikes |
| dot-stretch | dotStretch: true | boolean | true | When enabled, dots stretch when moving |
| dot-stretch-mult | dotStretchMult | number | 10 | How much to stretch dots |
| dot-max-stretch | dotMaxStretch | number | 20 | Maximum stretch amount |
| rot-smoothing | rotSmoothing | boolean | false | Smoothly rotates dots instead of snapping |
| rotsmoothingintensity | rotSmoothingIntensity | number | 150 | Rotation smoothing duration (ms) |
| dot-shape | dotShape | string | "circle" | Dot shape: "circle", "square", "triangle", "star", "image"; JS also accepts a custom draw function |
| dot-image | dotImage | string | null | Image URL used when dotShape is "image" |
| dot-colors | dotColors | array | null | Color palette; each dot picks one at random (overrides dotColor). HTML: comma-separated list |
| motion | motion | string | "none" | Autonomous motion preset: "none", "stream" or "vortex" |
| motion-angle | motionAngle | number | 0 | Stream direction in degrees (0 = right, 90 = down) |
| motion-strength | motionStrength | number | 0.05 | Strength of the motion preset force |
| motion-center-x | motionCenterX | number | 0.5 | Vortex center X as a fraction of canvas width (0-1) |
| motion-center-y | motionCenterY | number | 0.5 | Vortex center Y as a fraction of canvas height (0-1) |
<dot-wave
num-dots="400"
dot-color="white"
background-color="black"
dot-min-size="1"
dot-max-size="3"
dot-min-opacity="0.5"
dot-max-opacity="1"
influence-radius="100"
influence-strength="0.5"
random-factor="0.05"
friction="0.97"
max-speed="3"
reactive="true"
z-index="-1"
mouse-speed-decay="0.85"
max-mouse-speed="15"
dot-stretch="true"
dot-stretch-mult="10"
dot-max-stretch="20"
rot-smoothing="false"
rot-smoothing-intensity="150"
dot-shape="circle"
dot-image=""
dot-colors=""
motion="none"
motion-angle="0"
motion-strength="0.05"
motion-center-x="0.5"
motion-center-y="0.5">
</dot-wave>const dotwave = new DotWave({
container: 'body', // Container selector or DOM element
numDots: 400, // Number of dots
dotColor: 'white', // Dot color (CSS color)
backgroundColor: 'black', // Background color
dotMinSize: 1, // Minimum dot size
dotMaxSize: 3, // Maximum dot size
dotMinOpacity: 0.5, // Minimum dot opacity
dotMaxOpacity: 1, // Maximum dot opacity
influenceRadius: 100, // Mouse influence radius
influenceStrength: 0.5, // Mouse influence strength
randomFactor: 0.05, // Random movement factor
friction: 0.97, // Movement friction
maxSpeed: 3, // Maximum dot speed
reactive: true, // Toggle for cursor reactivity
zIndex: -1, // Canvas z-index
mouseSpeedDecay: 0.85, // How quickly mouse speed decays
maxMouseSpeed: 15, // Maximum mouse speed to prevent jumps
dotStretch: true, // Enable dot stretching based on velocity
dotStretchMult: 10, // How much to stretch the dots
dotMaxStretch: 20, // Maximum stretch amount
rotSmoothing: false, // Toggle for rotation smoothing of dots
rotSmoothingIntensity: 150, // Rotation smoothing duration in milliseconds
dotShape: 'circle', // Dot shape: 'circle', 'square', 'triangle', 'star', 'image' or a custom draw function
dotImage: null, // Image URL used when dotShape is 'image'
dotColors: null, // Array of colors; each dot picks one at random (overrides dotColor)
motion: 'none', // Autonomous motion preset: 'none', 'stream' or 'vortex'
motionAngle: 0, // Stream direction in degrees (0 = right, 90 = down)
motionStrength: 0.05, // Strength of the motion preset force
motionCenterX: 0.5, // Vortex center X as a fraction of canvas width (0-1)
motionCenterY: 0.5 // Vortex center Y as a fraction of canvas height (0-1)
});Note, that
rotSmoothing: falseskips the rotation lerping calculations and is therefore more performant than usingrotSmoothingIntensity: 0, same logic applies todotStretch.
Currently, DotWave targets 100 FPS and adjusts to the client frame rate using delta time for smooth motion scaling. Lower frame rates should work.
Contributions are welcome! Please feel free to submit a pull request or an issue. Feature requests are also welcome!
Some parts of the code for this project were generated by an LLM to save time
