I want to connect basic patterns to create decorative patterns combine with mouse interaction.
Simply put, what this code does is:
• Generate a dynamic grid, where each point oscillates over time.
The closer a point is to the center, the smaller its oscillation amplitude; the farther it is, the greater the amplitude.
Meanwhile, the center is bright in color, while the surrounding areas are dim.
• When the mouse approaches grid points, it affects their size and color.
• When the mouse moves quickly, it generates a halo effect.
➡️
1. Grid Pattern
Double for loop determines two directions
for (let x = 0; x < gridSize; x++) {
for (let y = 0; y < gridSize; y++) {
Calculate the current point's position * I wrote cellSize/2 to position the point at the center of the cell rather than at the top-left corner
let currentX = x * cellSize + cellSize/2;
let currentY = y * cellSize + cellSize/2;
Only draw lines when the point is not at the rightmost or bottommost position
if (x < gridSize-1 && y < gridSize-1) {
Calculate the positions of the right and bottom points (➡️&⬇️)
let rightX = (x + 1) * cellSize + cellSize/2;
let downY = (y + 1) * cellSize + cellSize/2;
Draw two lines: one to the right, one downward
line(currentX, currentY, rightX, currentY); Horizontal line
line(currentX, currentY, currentX, downY); Vertical line
2. Background motion
Calculate the distance from the point to the center of the canvas:
let distFromCenter = dist(baseX, baseY, width / 2, height / 2);
And use this to calculate the rotation angle:
let angle = frameCount * 0.015 + distFromCenter * 0.003;
frameCount * 0.015 is the base angle that changes over time
distFromCenter * 0.003: The farther the distance, the larger the initial angle.
Control movement amplitude:
let moveAmount = map(distFromCenter, 0, width / 2, 5, 25);
The farther from the center, the larger the movement amplitude.
sin(angle) and cos(angle) produce circular motion.
Final position calculation:
let finalX = baseX + sin(angle) * moveAmount * 0.5;
let finalY = baseY + cos(angle) * moveAmount * 0.5;
*The values 0.015, 0.003, and 0.5 above were determined through trial and error.
(It's moving)
3. (Reviewing and) applying noise()
🔑: noise(
x * 0.1, // X-coordinate influence (0.1 is a scale factor to slow changes)
y * 0.1, // Y-coordinate influence (0.1 makes adjacent points' values similar)
frameCount * 0.01 // Time influence (0.01 makes time changes smoother)
Line part
Use (x+1) and (y+1) to ensure adjacent points get different but related noise values, controlling motion amplitude:
let nextNoiseVal = noise((x+1) * 0.1, (y+1) * 0.1, frameCount * 0.01);
let nextFinalX = nextX + sin(nextAngle) * moveAmount * nextNoiseVal;
let nextFinalY = nextY + cos(nextAngle) * moveAmount * nextNoiseVal;
*Initially, I wanted to apply noise to the move part, but the effect was not good??
let noiseVal = noise(x * 0.1, y * 0.1, frameCount * 0.01);
let finalX = baseX + sin(angle) * moveAmount * noiseVal;
let finalY = baseY + cos(angle) * moveAmount * noiseVal;
However, I still recorded the experimental results:
noise(x * 0.05, y * 0.05, frameCount * 0.01); Smoother variation
noise(x * 0.2, y * 0.2, frameCount * 0.01); More intense variation
noise(x * 0.1, y * 0.1, frameCount * 0.02); Faster changes
4. RGB color settings:
Regular gradient based on time that I use:
let r = map(sin(frameCount * 0.02), -1, 1, 100, 255);
let g = map(cos(frameCount * 0.02), -1, 1, 150, 255);
let b = 255;
sin(frameCount * 0.02) and cos(frameCount * 0.02) make r and g change over time.
sin() and cos() values are in [-1, 1], so map() maps them to [100, 255] (red) and [150, 255] (green).
b = 255 keeps blue at full brightness, ensuring an overall blue color tone.
Adding position-based variation:
let r = map(sin(distFromCenter * 0.01 + frameCount * 0.02), -1, 1, 50, 150);
distFromCenter * 0.01 makes colors change based on position, ensuring adjacent points have different colors.
5. Particle effect without using arrays (actually I forgot how to use them)
Use loops and trigonometric functions instead of arrays
for (let i = 0; i < 12; i++) {
Use i to calculate each point's position:
let angle = frameCount * 0.1 + i * TWO_PI / 12; Evenly distributed around a circle!!
let radius = 100 + sin(frameCount * 0.1 + i) * 20; Dynamic radius
*Each frame, positions are recalculated, no need to store particle states:
let x = mouseX + cos(angle) * radius;
let y = mouseY + sin(angle) * radius;
circle(x, y, particleSize);
(Final version)
*6. If change blend mode
Code
let gridSize = 15;
function setup() {
createCanvas(600, 600);
angleMode(RADIANS);
}
function draw() {
background(20, 22, 30);
// gridsize
let cellSize = width / gridSize;
// pattern
for (let x = 0; x < gridSize; x++) {
for (let y = 0; y < gridSize; y++) {
// initial
let baseX = x * cellSize + cellSize/2;
let baseY = y * cellSize + cellSize/2;
// move
let distFromCenter = dist(baseX, baseY, width/2, height/2);
let angle = frameCount * 0.015 + distFromCenter * 0.003;
let moveAmount = map(distFromCenter, 0, width/2, 5, 25);
// final
let finalX = baseX + sin(angle) * moveAmount * 0.5;
let finalY = baseY + cos(angle) * moveAmount * 0.5;
push();
translate(finalX, finalY);
// lines
if (x < gridSize-1 && y < gridSize-1) {
let nextX = (x + 1) * cellSize + cellSize/2;
let nextY = (y + 1) * cellSize + cellSize/2;
let nextAngle = frameCount * 0.015 + dist(nextX, nextY, width/2, height/2) * 0.003;
let nextNoiseVal = noise((x+1) * 0.1, (y+1) * 0.1, frameCount * 0.01);
let nextFinalX = nextX + sin(nextAngle) * moveAmount * nextNoiseVal;
let nextFinalY = nextY + cos(nextAngle) * moveAmount * nextNoiseVal;
// RBG gradiant
let alpha = map(distFromCenter, 0, width/2, 250, 10);
let r = map(sin(frameCount * 0.02), -1, 1, 100, 255);
let g = map(cos(frameCount * 0.02), -1, 1, 150, 255);
let b = 255;
stroke(r, g, b, alpha);
strokeWeight(0.5);
line(0, 0, nextFinalX - finalX, 0);
line(0, 0, 0, nextFinalY - finalY);
}
// dot
let mouseD = dist(mouseX, mouseY, finalX, finalY);
if (mouseD < 150) {
let dotSize = map(mouseD, 0, 150, 8, 2);
noStroke();
//RBG
let r = map(sin(distFromCenter * 0.01 + frameCount * 0.02), -1, 1, 50, 150);
let g = map(cos(distFromCenter * 0.01 + frameCount * 0.02), -1, 1, 100, 200);
let b = map(sin(distFromCenter * 0.01 + frameCount * 0.03), -1, 1, 200, 255);
fill(r, g, b, 200);
circle(0, 0, dotSize + sin(frameCount * 0.1 + x * y) * 2);
}
pop();
}
}
// mouse
let mouseSpeed = dist(mouseX, mouseY, pmouseX, pmouseY);
if (mouseSpeed > 5) {
for (let i = 0; i < 12; i++) {
let angle = frameCount * 0.1 + i * TWO_PI / 12;
let radius = 100 + sin(frameCount * 0.1 + i) * 20;
let x = mouseX + cos(angle) * radius;
let y = mouseY + sin(angle) * radius;
// RGB moving
let r = map(sin(i * 0.5 + frameCount * 0.02), -1, 1, 50, 150);
let g = map(cos(i * 0.5 + frameCount * 0.02), -1, 1, 100, 200);
let b = map(sin(i * 0.5 + frameCount * 0.03), -1, 1, 200, 255);
stroke(r, g, b, 100);
strokeWeight(1);
line(mouseX, mouseY, x, y);
// linedot
noStroke();
fill(r, g, b, 200);
let particleSize = 3 + sin(frameCount * 0.1 + i) * 2;
circle(x, y, particleSize);
}
}
}