particle field planning
All checks were successful
deploy / build-and-deploy (push) Successful in 31s
All checks were successful
deploy / build-and-deploy (push) Successful in 31s
This commit is contained in:
parent
ae60a7c856
commit
f4b8e1a7d8
5 changed files with 1685 additions and 0 deletions
161
reference/particle-field-demo/README.md
Normal file
161
reference/particle-field-demo/README.md
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
# particle-network
|
||||
|
||||
A canvas animation of drifting particles connected by proximity lines, with
|
||||
opacity modulated by a slowly-rolling fBm (fractal Brownian motion) noise field.
|
||||
|
||||
No external dependencies. Pure ES module.
|
||||
|
||||
---
|
||||
|
||||
## Files
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `particleNetwork.js` | The module — import this into your project |
|
||||
| `demo.html` | Minimal working example (requires a local server for ES module import) |
|
||||
|
||||
---
|
||||
|
||||
## Quick start
|
||||
|
||||
Serve the folder with any static server, e.g.:
|
||||
|
||||
```bash
|
||||
npx serve .
|
||||
# or
|
||||
python3 -m http.server
|
||||
```
|
||||
|
||||
Then open `demo.html`.
|
||||
|
||||
---
|
||||
|
||||
## Integration
|
||||
|
||||
### 1. Minimal — full-page background
|
||||
|
||||
```html
|
||||
<canvas id="net"></canvas>
|
||||
|
||||
<script type="module">
|
||||
import { ParticleNetwork } from './particleNetwork.js';
|
||||
|
||||
const canvas = document.getElementById('net');
|
||||
|
||||
// Size the canvas to the viewport yourself, or let the module
|
||||
// read the parent element's bounding rect (default behaviour).
|
||||
canvas.style.display = 'block';
|
||||
canvas.style.width = '100%';
|
||||
|
||||
const net = new ParticleNetwork(canvas, null);
|
||||
net.start();
|
||||
</script>
|
||||
```
|
||||
|
||||
### 2. With field preview (debug / design mode)
|
||||
|
||||
```html
|
||||
<canvas id="net"></canvas>
|
||||
<canvas id="field"></canvas>
|
||||
|
||||
<script type="module">
|
||||
import { ParticleNetwork } from './particleNetwork.js';
|
||||
|
||||
const net = new ParticleNetwork(
|
||||
document.getElementById('net'),
|
||||
document.getElementById('field'),
|
||||
{ count: 60, dimAtMin: 0.5 }
|
||||
);
|
||||
|
||||
net.start();
|
||||
</script>
|
||||
```
|
||||
|
||||
### 3. Bundler / framework
|
||||
|
||||
Copy `particleNetwork.js` anywhere in your `src/` tree and import normally:
|
||||
|
||||
```js
|
||||
import { ParticleNetwork } from '@/lib/particleNetwork.js';
|
||||
```
|
||||
|
||||
No build config changes needed — it uses only standard browser APIs.
|
||||
|
||||
---
|
||||
|
||||
## Constructor
|
||||
|
||||
```js
|
||||
new ParticleNetwork(mainCanvas, fieldCanvas, options)
|
||||
```
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `mainCanvas` | `HTMLCanvasElement` | The particle animation canvas |
|
||||
| `fieldCanvas` | `HTMLCanvasElement \| null` | Optional debug field view |
|
||||
| `options` | `object` | See below |
|
||||
|
||||
---
|
||||
|
||||
## Options
|
||||
|
||||
All options can be passed at construction time and updated at runtime via
|
||||
`setOption(key, value)`.
|
||||
|
||||
| Key | Default | Description |
|
||||
|-----|---------|-------------|
|
||||
| `count` | `55` | Number of particles |
|
||||
| `reach` | `140` | Max connection distance in canvas px |
|
||||
| `flowSpeed` | `2` | Field drift speed on a 1–10 scale. At 1, motion takes several minutes to traverse the field — clearly present but takes time to perceive. |
|
||||
| `fieldScale` | `4` | Noise zoom on a 1–10 scale. Lower = larger rolling blobs. |
|
||||
| `dimAtMin` | `0.60` | Opacity reduction at field minimum. `0` = field has no opacity effect. `1` = particles in troughs are fully invisible. |
|
||||
| `particleSpeed` | `0.35` | Base particle velocity (px/frame) |
|
||||
| `particleMinR` | `1.4` | Minimum particle radius (px) |
|
||||
| `particleMaxR` | `2.8` | Maximum particle radius (px) |
|
||||
| `fieldUpdateMs` | `50` | How often the noise field recalculates (ms). Lower = smoother but more CPU. |
|
||||
| `fieldOctaves` | `4` | fBm octaves. More = finer detail, more CPU. |
|
||||
| `bgColor` | `'#040e1f'` | Canvas background colour |
|
||||
| `lineColor` | `'80,160,240'` | RGB string for particle–particle lines |
|
||||
| `lineColorMouse` | `'160,220,255'` | RGB string for mouse-proximity lines |
|
||||
| `canvasAspect` | `0.65` | Canvas height = width × aspect |
|
||||
| `timeConstantX` | `0.00084` | Primary axis time advance rate. Halve to slow further. |
|
||||
| `timeConstantY` | `0.0003145` | Secondary axis rate — kept at a different ratio for the swirling character. |
|
||||
|
||||
---
|
||||
|
||||
## Methods
|
||||
|
||||
```js
|
||||
net.start() // begin animation loop
|
||||
net.stop() // pause (preserves state)
|
||||
net.setOption(key, value) // update any option at runtime
|
||||
net.sampleField(x, y) // returns [0,1] field value at canvas coords
|
||||
net.destroy() // stop loop and remove all event listeners
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## How it works
|
||||
|
||||
**Noise field** — a 4-octave fBm Perlin noise function is evaluated on a tiny
|
||||
80×52 offscreen canvas every 50ms, then scaled up via `drawImage`. This is
|
||||
~100× cheaper than evaluating at display resolution.
|
||||
|
||||
**Opacity mapping** — each particle's field sample `fv ∈ [0,1]` maps to an
|
||||
opacity multiplier via:
|
||||
|
||||
```
|
||||
multiplier = (1 - dimAtMin) + dimAtMin * fv
|
||||
```
|
||||
|
||||
At `fv = 1` (field peak): multiplier = 1.0 — full brightness.
|
||||
At `fv = 0` (field trough): multiplier = 1 - dimAtMin.
|
||||
|
||||
For connecting lines the multiplier is the geometric mean of both endpoint
|
||||
values, so a line straddling a bright and dark zone stays dim.
|
||||
|
||||
**Distance falloff** — cubic: `(1 - dist/reach)³`, giving a sharp fade near
|
||||
the connection threshold rather than a linear fade across the full range.
|
||||
|
||||
**Glow** — each particle renders a `createRadialGradient` halo sized to
|
||||
`r × (2.5 + fieldValue × 1.5)`, so dots in bright field regions bloom larger.
|
||||
Loading…
Add table
Add a link
Reference in a new issue