-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathp23.js
More file actions
112 lines (97 loc) · 3.49 KB
/
Copy pathp23.js
File metadata and controls
112 lines (97 loc) · 3.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/**
* Generative Art exercise from Tim Holman's Speedrun talk, CSSConf Australia 2018
* Reference: https://www.youtube.com/watch?v=4Se0_w0ISYk
* Timer: 14:29
*
* Practice 23: Colors - Pipes - Part 2 - Alt Coloring
* Code by Jace Yang
*/
const NUM_LINES = 20; // Control the number of lines
const COLORS = [
'hsl(190, 10%, 86%)', // #dae0e1 converted to HSL
'hsl(210, 37%, 28%)', // #2c4860 converted to HSL
'hsl(189, 38%, 69%)' // #94c5cc converted to HSL
];
const NUM_ITERATIONS = 16; // Control the number of twists
const NO_SWAP_PROBABILITY = 0.6; // Control the probability of straight segments
function setup() {
createCanvas(400, 400);
drawSquare();
drawThinSquare();
}
function drawSquare() {
background(255);
push();
drawingContext.shadowOffsetX = -5;
drawingContext.shadowOffsetY = 0;
drawingContext.shadowBlur = 10;
drawingContext.shadowColor = 'rgba(0, 0, 0, 0.5)';
stroke(0);
strokeWeight(5);
line(50, 50, 50, 350);
pop();
push();
drawingContext.shadowOffsetX = 0;
drawingContext.shadowOffsetY = 5;
drawingContext.shadowBlur = 10;
drawingContext.shadowColor = 'rgba(0, 0, 0, 0.5)';
stroke(0);
strokeWeight(5);
line(50, 350, 350, 350);
pop();
stroke(0);
strokeWeight(10);
noFill();
rect(50, 50, 300, 300);
}
function drawThinSquare() {
const startY = 80;
const endY = 320;
const totalHeight = endY - startY;
const spacing = 240 / (NUM_LINES - 1);
const MOVE_DISTANCE = totalHeight / NUM_ITERATIONS;
push();
drawingContext.lineJoin = 'round';
strokeWeight(3);
// 1. Initialize position history with original indices
let positionHistory = [Array.from({length: NUM_LINES}, (_, i) => i)];
// 2. Precompute position swaps for all iterations
for(let iter = 0; iter < NUM_ITERATIONS; iter++) {
const newPositions = [...positionHistory[iter]];
let i = 0;
// Pairwise swapping with probability check
while(i < NUM_LINES) {
if(random() < NO_SWAP_PROBABILITY || i === NUM_LINES - 1) {
i++; // No swap
} else {
[newPositions[i], newPositions[i + 1]] = [newPositions[i + 1], newPositions[i]];
i += 2; // Skip swapped pair
}
}
positionHistory.push(newPositions);
}
// 3. Draw continuous bezier curves for each original line
const centerIndex = Math.floor(NUM_LINES / 2);
for(let originalIdx = 0; originalIdx < NUM_LINES; originalIdx++) {
beginShape();
// Use red only for center line, new palette for others
originalIdx === centerIndex
? stroke('hsl(344, 85%, 61%)')
: stroke(COLORS[originalIdx % COLORS.length]);
for(let iter = 0; iter <= NUM_ITERATIONS; iter++) {
const pos = positionHistory[iter].indexOf(originalIdx);
const x = 80 + (pos * spacing);
const y = startY + (iter * MOVE_DISTANCE);
// Create smooth bezier curves between positions
iter === 0 ? vertex(x, y) : bezierVertex(
prevX, prevY + (MOVE_DISTANCE * 0.3), // Control point 1
x, y - (MOVE_DISTANCE * 0.3), // Control point 2
x, y // Current position
);
// Store previous position for next iteration
[prevX, prevY] = [x, y];
}
endShape();
}
pop();
}