π€ AI
Hereβs a complete version of your project with a pulsing concentric ring / radar-ripple effect using neon pink, cyan, and purple on a dark background.
### Files
#### `index.html`
Make sure p5.js is loaded before `sketch.js`:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Pulsing Neon Rings</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<!-- p5.js core library -->
<script src="https://cdn.jsdelivr.net/npm/p5@1.11.3/lib/p5.min.js"></script>
<!-- your sketch -->
<script src="sketch.js"></script>
</body>
</html>
```
#### `style.css`
You can keep this as-is:
```css
body {
margin: 0;
padding: 0;
overflow: hidden;
background: #000; /* fallback background behind canvas */
}
canvas {
display: block;
}
```
#### `sketch.js`
Pulsing concentric rings with neon colors, expanding and fading from the center:
```js
// Pulsing neon rings / radar-style ripples
let rings = [];
let spawnInterval = 250; // ms between new rings
let lastSpawnTime = 0;
let ringDuration = 2000; // how long each ring lives in ms
let maxRadius;
let palette = [];
function setup() {
createCanvas(windowWidth, windowHeight);
// Use HSB for easier neon color control
colorMode(HSB, 360, 100, 100, 255);
noFill();
maxRadius = min(width, height) * 0.6;
// Neon color palette: pink, cyan, purple
palette = [
color(320, 100, 100), // neon pink
color(185, 100, 100), // cyan
color(270, 100, 100) // purple
];
background(0, 0, 0); // pure black (HSB: any hue, 0 sat, 0 bright)
}
function draw() {
// Slight transparency for a soft trailing effect
// HSB: hue doesn't matter when saturation is 0; this is just "almost black"
background(0, 0, 0, 40);
const now = millis();
// Spawn new rings at regular time intervals
if (now - lastSpawnTime >= spawnInterval) {
spawnRing();
lastSpawnTime = now;
}
// Update and draw rings, remove dead ones
for (let i = rings.length - 1; i >= 0; i--) {
rings[i].draw();
if (rings[i].isDead()) {
rings.splice(i, 1);
}
}
}
function spawnRing() {
const centerX = width / 2;
const centerY = height / 2;
const col = random(palette); // pick a random neon color
rings.push(new Ring(centerX, centerY, maxRadius, ringDuration, col));
}
class Ring {
constructor(x, y, maxRadius, lifetime, col) {
this.x = x;
this.y = y;
this.maxRadius = maxRadius;
this.lifetime = lifetime; // in ms
this.birth = millis();
this.col = col;
}
draw() {
const age = millis() - this.birth;
const t = constrain(age / this.lifetime, 0, 1); // 0 β 1 over lifetime
const radius = lerp(0, this.maxRadius, t);
const alpha = lerp(255, 0, t); // fade out
const weight = lerp(4, 1, t); // thinner as it grows
const base = this.col;
const c = color(
hue(base),
saturation(base),
brightness(base),
alpha
);
stroke(c);
strokeWeight(weight);
// p5 circle reference: https://p5js.org/reference/#/p5/circle
circle(this.x, this.y, radius * 2);
}
isDead() {
return millis() - this.birth > this.lifetime;
}
}
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
maxRadius = min(width, height) * 0.6;
}
```
Notes:
- Rings spawn from the center at fixed time intervals (`spawnInterval`).
- Each ring grows from radius 0 to `maxRadius` over `ringDuration` ms while its alpha fades from 255 to 0.
- Background is dark and slightly transparent each frame to create a soft radar-like trail. If you prefer no trails, change:
```js
background(0, 0, 0, 40);
```
to:
```js
background(0, 0, 0);
```
If you want the pulses to be faster/slower or have more/less overlap, tweak `spawnInterval` and `ringDuration`.