git-hash-art 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.kiro/steering/product.md +16 -0
- package/.kiro/steering/structure.md +40 -0
- package/.kiro/steering/tech.md +24 -0
- package/ALGORITHM.md +198 -0
- package/CHANGELOG.md +19 -0
- package/README.md +165 -57
- package/dist/browser.js +1430 -0
- package/dist/browser.js.map +1 -0
- package/dist/main.js +672 -333
- package/dist/main.js.map +1 -1
- package/dist/module.js +665 -329
- package/dist/module.js.map +1 -1
- package/dist/types.d.ts +2 -9
- package/dist/types.d.ts.map +1 -1
- package/package.json +47 -3
- package/src/__tests__/compatibility.test.ts +42 -0
- package/src/__tests__/generation.test.ts +58 -0
- package/src/__tests__/render.test.ts +81 -0
- package/src/__tests__/shapes.test.ts +71 -0
- package/src/browser.ts +100 -0
- package/src/index.ts +38 -199
- package/src/lib/canvas/colors.ts +90 -66
- package/src/lib/canvas/draw.ts +38 -7
- package/src/lib/canvas/shapes/basic.ts +1 -1
- package/src/lib/canvas/shapes/complex.ts +2 -1
- package/src/lib/render.ts +483 -0
- package/src/lib/utils.ts +33 -6
- package/src/types.ts +35 -0
package/dist/browser.js
ADDED
|
@@ -0,0 +1,1430 @@
|
|
|
1
|
+
import $4wRzV$colorscheme from "color-scheme";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Browser entry point for git-hash-art.
|
|
5
|
+
*
|
|
6
|
+
* This module has zero Node.js dependencies — it works with a standard
|
|
7
|
+
* HTMLCanvasElement or OffscreenCanvas and the native Canvas 2D API.
|
|
8
|
+
*/ /**
|
|
9
|
+
* Pure rendering logic — environment-agnostic.
|
|
10
|
+
*
|
|
11
|
+
* Uses only the standard CanvasRenderingContext2D API so it works
|
|
12
|
+
* identically in Node (@napi-rs/canvas) and browsers.
|
|
13
|
+
*
|
|
14
|
+
* Generation pipeline:
|
|
15
|
+
* 1. Background — radial gradient from hash-derived dark palette
|
|
16
|
+
* 2. Composition mode — hash selects: radial, flow-field, spiral, grid-subdivision, or clustered
|
|
17
|
+
* 3. Color field — smooth positional color blending across the canvas
|
|
18
|
+
* 4. Shape layers — weighted selection, focal-point placement, transparency, glow, gradients, jitter
|
|
19
|
+
* 5. Recursive nesting — some shapes contain smaller shapes inside
|
|
20
|
+
* 6. Flow-line pass — bezier curves following a hash-derived vector field
|
|
21
|
+
* 7. Noise texture overlay — subtle grain for organic feel
|
|
22
|
+
* 8. Organic connecting curves — beziers between nearby shapes
|
|
23
|
+
*/
|
|
24
|
+
// declare module 'color-scheme';
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
function $616009579e3d72c5$export$39a95c82b20fdf81(gitHash) {
|
|
28
|
+
return parseInt(gitHash.slice(0, 8), 16);
|
|
29
|
+
}
|
|
30
|
+
function $616009579e3d72c5$export$eaf9227667332084(seed) {
|
|
31
|
+
let s = seed | 0;
|
|
32
|
+
return ()=>{
|
|
33
|
+
s = s + 0x6d2b79f5 | 0;
|
|
34
|
+
let t = Math.imul(s ^ s >>> 15, 1 | s);
|
|
35
|
+
t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
|
|
36
|
+
return ((t ^ t >>> 14) >>> 0) / 4294967296;
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function $616009579e3d72c5$export$e9cc707de01b7042(hash, offset = 0) {
|
|
40
|
+
let h = 0;
|
|
41
|
+
for(let i = 0; i < hash.length; i++)h = Math.imul(31, h) + hash.charCodeAt(i) | 0;
|
|
42
|
+
return h + offset | 0;
|
|
43
|
+
}
|
|
44
|
+
function $616009579e3d72c5$export$6b193cae730c547a(hash, index, min, max) {
|
|
45
|
+
const rng = $616009579e3d72c5$export$eaf9227667332084($616009579e3d72c5$export$e9cc707de01b7042(hash, index));
|
|
46
|
+
return min + rng() * (max - min);
|
|
47
|
+
}
|
|
48
|
+
const $616009579e3d72c5$export$bb9e4790bc99ae59 = {
|
|
49
|
+
GOLDEN_RATIO: 1.618034,
|
|
50
|
+
SQUARE_ROOT_2: Math.sqrt(2),
|
|
51
|
+
SQUARE_ROOT_3: Math.sqrt(3),
|
|
52
|
+
SQUARE_ROOT_5: Math.sqrt(5),
|
|
53
|
+
PI: Math.PI,
|
|
54
|
+
PHI: (1 + Math.sqrt(5)) / 2
|
|
55
|
+
};
|
|
56
|
+
class $616009579e3d72c5$export$da2372f11bc66b3f {
|
|
57
|
+
static getProportionalSize(baseSize, proportion) {
|
|
58
|
+
return baseSize * proportion;
|
|
59
|
+
}
|
|
60
|
+
static centerPattern(ctx, width, height) {
|
|
61
|
+
ctx.translate(width / 2, height / 2);
|
|
62
|
+
}
|
|
63
|
+
// Combines sacred geometry patterns with proper proportions
|
|
64
|
+
static layerPatterns(ctx, patterns, config) {
|
|
65
|
+
const { baseSize: baseSize, baseOpacity: baseOpacity = 0.6, opacityReduction: opacityReduction = 0.1, rotationOffset: rotationOffset = 0, proportionType: proportionType = "GOLDEN_RATIO" } = config;
|
|
66
|
+
patterns.forEach((pattern, index)=>{
|
|
67
|
+
const size = this.getProportionalSize(baseSize, Math.pow($616009579e3d72c5$export$bb9e4790bc99ae59[proportionType], index));
|
|
68
|
+
const opacity = Math.max(0.1, baseOpacity - index * opacityReduction);
|
|
69
|
+
const rotation = rotationOffset * index;
|
|
70
|
+
ctx.save();
|
|
71
|
+
ctx.globalAlpha = opacity;
|
|
72
|
+
ctx.rotate(rotation * Math.PI / 180);
|
|
73
|
+
shapes[pattern.type](ctx, size, pattern.config);
|
|
74
|
+
ctx.restore();
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
function $b5a262d09b87e373$export$f116a24fd288e742(gitHash) {
|
|
81
|
+
const seed = (0, $616009579e3d72c5$export$39a95c82b20fdf81)(gitHash);
|
|
82
|
+
const scheme = new (0, $4wRzV$colorscheme)();
|
|
83
|
+
scheme.from_hue(seed % 360).scheme("analogic").variation("soft");
|
|
84
|
+
let colors = scheme.colors().map((hex)=>`#${hex}`);
|
|
85
|
+
const contrastingHue = (seed + 180) % 360;
|
|
86
|
+
const contrastingScheme = new (0, $4wRzV$colorscheme)();
|
|
87
|
+
contrastingScheme.from_hue(contrastingHue).scheme("mono").variation("soft");
|
|
88
|
+
colors.push(`#${contrastingScheme.colors()[0]}`);
|
|
89
|
+
return colors;
|
|
90
|
+
}
|
|
91
|
+
class $b5a262d09b87e373$export$ab958c550f521376 {
|
|
92
|
+
constructor(gitHash){
|
|
93
|
+
this.seed = (0, $616009579e3d72c5$export$39a95c82b20fdf81)(gitHash);
|
|
94
|
+
this.baseScheme = this.generateBaseScheme();
|
|
95
|
+
this.complementaryScheme = this.generateComplementaryScheme();
|
|
96
|
+
this.triadicScheme = this.generateTriadicScheme();
|
|
97
|
+
this.metallic = this.generateMetallicColors();
|
|
98
|
+
}
|
|
99
|
+
generateBaseScheme() {
|
|
100
|
+
const scheme = new (0, $4wRzV$colorscheme)();
|
|
101
|
+
return scheme.from_hue(this.seed % 360).scheme("analogic").variation("soft").colors().map((hex)=>`#${hex}`);
|
|
102
|
+
}
|
|
103
|
+
generateComplementaryScheme() {
|
|
104
|
+
const complementaryHue = (this.seed + 180) % 360;
|
|
105
|
+
const scheme = new (0, $4wRzV$colorscheme)();
|
|
106
|
+
return scheme.from_hue(complementaryHue).scheme("mono").variation("soft").colors().map((hex)=>`#${hex}`);
|
|
107
|
+
}
|
|
108
|
+
generateTriadicScheme() {
|
|
109
|
+
const triadicHue = (this.seed + 120) % 360;
|
|
110
|
+
const scheme = new (0, $4wRzV$colorscheme)();
|
|
111
|
+
return scheme.from_hue(triadicHue).scheme("triade").variation("soft").colors().map((hex)=>`#${hex}`);
|
|
112
|
+
}
|
|
113
|
+
generateMetallicColors() {
|
|
114
|
+
return {
|
|
115
|
+
gold: "#FFD700",
|
|
116
|
+
silver: "#C0C0C0",
|
|
117
|
+
copper: "#B87333",
|
|
118
|
+
bronze: "#CD7F32"
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Returns a flat array of hash-derived colors suitable for art generation.
|
|
123
|
+
* Combines base analogic, complementary, and triadic schemes for variety
|
|
124
|
+
* while maintaining color harmony.
|
|
125
|
+
*/ getColors() {
|
|
126
|
+
// Deduplicate and return a rich palette
|
|
127
|
+
const all = [
|
|
128
|
+
...this.baseScheme.slice(0, 4),
|
|
129
|
+
...this.complementaryScheme.slice(0, 2),
|
|
130
|
+
...this.triadicScheme.slice(0, 2)
|
|
131
|
+
];
|
|
132
|
+
return [
|
|
133
|
+
...new Set(all)
|
|
134
|
+
];
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Returns two background colors derived from the hash — darker variants
|
|
138
|
+
* of the base scheme for gradient backgrounds.
|
|
139
|
+
*/ getBackgroundColors() {
|
|
140
|
+
return [
|
|
141
|
+
this.darken(this.baseScheme[0], 0.65),
|
|
142
|
+
this.darken(this.baseScheme[1], 0.55)
|
|
143
|
+
];
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Simple hex color darkening by a factor (0 = black, 1 = unchanged).
|
|
147
|
+
*/ darken(hex, factor) {
|
|
148
|
+
const c = hex.replace("#", "");
|
|
149
|
+
const r = Math.round(parseInt(c.substring(0, 2), 16) * factor);
|
|
150
|
+
const g = Math.round(parseInt(c.substring(2, 4), 16) * factor);
|
|
151
|
+
const b = Math.round(parseInt(c.substring(4, 6), 16) * factor);
|
|
152
|
+
return `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
// ── Standalone color utilities ──────────────────────────────────────
|
|
156
|
+
/** Parse a hex color (#RRGGBB) into [r, g, b] 0-255. */ function $b5a262d09b87e373$var$hexToRgb(hex) {
|
|
157
|
+
const c = hex.replace("#", "");
|
|
158
|
+
return [
|
|
159
|
+
parseInt(c.substring(0, 2), 16),
|
|
160
|
+
parseInt(c.substring(2, 4), 16),
|
|
161
|
+
parseInt(c.substring(4, 6), 16)
|
|
162
|
+
];
|
|
163
|
+
}
|
|
164
|
+
/** Format [r, g, b] back to #RRGGBB. */ function $b5a262d09b87e373$var$rgbToHex(r, g, b) {
|
|
165
|
+
const clamp = (v)=>Math.max(0, Math.min(255, Math.round(v)));
|
|
166
|
+
return `#${clamp(r).toString(16).padStart(2, "0")}${clamp(g).toString(16).padStart(2, "0")}${clamp(b).toString(16).padStart(2, "0")}`;
|
|
167
|
+
}
|
|
168
|
+
function $b5a262d09b87e373$export$f2121afcad3d553f(hex, alpha) {
|
|
169
|
+
const [r, g, b] = $b5a262d09b87e373$var$hexToRgb(hex);
|
|
170
|
+
return `rgba(${r},${g},${b},${alpha.toFixed(3)})`;
|
|
171
|
+
}
|
|
172
|
+
function $b5a262d09b87e373$export$59539d800dbe6858(hex, rng, amount = 0.1) {
|
|
173
|
+
const [r, g, b] = $b5a262d09b87e373$var$hexToRgb(hex);
|
|
174
|
+
const jit = ()=>(rng() - 0.5) * 2 * amount * 255;
|
|
175
|
+
return $b5a262d09b87e373$var$rgbToHex(r + jit(), g + jit(), b + jit());
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
const $44f5b87a40c9680b$export$8daab6f91f7ff730 = (ctx, size)=>{
|
|
181
|
+
ctx.beginPath();
|
|
182
|
+
ctx.arc(0, 0, size / 2, 0, Math.PI * 2);
|
|
183
|
+
};
|
|
184
|
+
const $44f5b87a40c9680b$export$9340b6a85ea854b9 = (ctx, size)=>{
|
|
185
|
+
ctx.beginPath();
|
|
186
|
+
ctx.rect(-size / 2, -size / 2, size, size);
|
|
187
|
+
};
|
|
188
|
+
const $44f5b87a40c9680b$export$e6b70c7883316010 = (ctx, size)=>{
|
|
189
|
+
ctx.beginPath();
|
|
190
|
+
ctx.moveTo(0, -size / 2);
|
|
191
|
+
ctx.lineTo(-size / 2, size / 2);
|
|
192
|
+
ctx.lineTo(size / 2, size / 2);
|
|
193
|
+
ctx.closePath();
|
|
194
|
+
};
|
|
195
|
+
const $44f5b87a40c9680b$export$252d2895fb67397b = (ctx, size)=>{
|
|
196
|
+
ctx.beginPath();
|
|
197
|
+
for(let i = 0; i < 6; i++){
|
|
198
|
+
const angle = Math.PI * 2 / 6 * i;
|
|
199
|
+
const x = size / 2 * Math.cos(angle);
|
|
200
|
+
const y = size / 2 * Math.sin(angle);
|
|
201
|
+
if (i === 0) ctx.moveTo(x, y);
|
|
202
|
+
else ctx.lineTo(x, y);
|
|
203
|
+
}
|
|
204
|
+
ctx.closePath();
|
|
205
|
+
};
|
|
206
|
+
const $44f5b87a40c9680b$export$ca57b923902a3c0 = (ctx, size)=>{
|
|
207
|
+
ctx.beginPath();
|
|
208
|
+
for(let i = 0; i < 10; i++){
|
|
209
|
+
const angle = Math.PI / 5 + Math.PI / 5 * i * 3;
|
|
210
|
+
const radius = i % 2 === 0 ? size / 2 : size / 4;
|
|
211
|
+
const x = radius * Math.cos(angle);
|
|
212
|
+
const y = radius * Math.sin(angle);
|
|
213
|
+
if (i === 0) ctx.moveTo(x, y);
|
|
214
|
+
else ctx.lineTo(x, y);
|
|
215
|
+
}
|
|
216
|
+
ctx.closePath();
|
|
217
|
+
};
|
|
218
|
+
const $44f5b87a40c9680b$export$cf8f2f05ac4f561f = (ctx, size)=>{
|
|
219
|
+
ctx.beginPath();
|
|
220
|
+
for(let i = 0; i < 10; i++){
|
|
221
|
+
const angle = Math.PI / 30 + Math.PI / 30 * i * 8;
|
|
222
|
+
const radius = i % 2 === 0 ? size / 2 : size / 8;
|
|
223
|
+
const x = radius * Math.cos(angle);
|
|
224
|
+
const y = radius * Math.sin(angle);
|
|
225
|
+
if (i === 0) ctx.moveTo(x, y);
|
|
226
|
+
else ctx.lineTo(x, y);
|
|
227
|
+
}
|
|
228
|
+
ctx.closePath();
|
|
229
|
+
};
|
|
230
|
+
const $44f5b87a40c9680b$export$1ed0c0bc398b6246 = (ctx, size)=>{
|
|
231
|
+
ctx.beginPath();
|
|
232
|
+
ctx.moveTo(0, size / 4);
|
|
233
|
+
ctx.quadraticCurveTo(size / 2, size / 4, 0, -size / 4);
|
|
234
|
+
ctx.quadraticCurveTo(-size / 2, size / 4, 0, size / 4);
|
|
235
|
+
};
|
|
236
|
+
const $44f5b87a40c9680b$export$57ec12daf141ce6 = (ctx, size)=>{
|
|
237
|
+
ctx.beginPath();
|
|
238
|
+
ctx.moveTo(0, -size / 2);
|
|
239
|
+
ctx.lineTo(size / 2, 0);
|
|
240
|
+
ctx.lineTo(0, size / 2);
|
|
241
|
+
ctx.lineTo(-size / 2, 0);
|
|
242
|
+
ctx.closePath();
|
|
243
|
+
};
|
|
244
|
+
const $44f5b87a40c9680b$export$39f25a4fc5491539 = (ctx, size)=>{
|
|
245
|
+
ctx.beginPath();
|
|
246
|
+
ctx.moveTo(-size / 2, -size / 2);
|
|
247
|
+
ctx.lineTo(size / 2, -size / 2);
|
|
248
|
+
ctx.lineTo(size / 2, size / 2);
|
|
249
|
+
ctx.lineTo(-size / 2, size / 2);
|
|
250
|
+
ctx.closePath();
|
|
251
|
+
};
|
|
252
|
+
const $44f5b87a40c9680b$export$492753207a5258e1 = {
|
|
253
|
+
circle: $44f5b87a40c9680b$export$8daab6f91f7ff730,
|
|
254
|
+
square: $44f5b87a40c9680b$export$9340b6a85ea854b9,
|
|
255
|
+
triangle: $44f5b87a40c9680b$export$e6b70c7883316010,
|
|
256
|
+
hexagon: $44f5b87a40c9680b$export$252d2895fb67397b,
|
|
257
|
+
star: $44f5b87a40c9680b$export$ca57b923902a3c0,
|
|
258
|
+
"jacked-star": $44f5b87a40c9680b$export$cf8f2f05ac4f561f,
|
|
259
|
+
heart: $44f5b87a40c9680b$export$1ed0c0bc398b6246,
|
|
260
|
+
diamond: $44f5b87a40c9680b$export$57ec12daf141ce6,
|
|
261
|
+
cube: $44f5b87a40c9680b$export$39f25a4fc5491539
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
// Define interfaces for our configurations
|
|
266
|
+
const $e0ea14d2e2f06463$export$9265403940be6b4 = {
|
|
267
|
+
// Standard sizes with different hashes
|
|
268
|
+
react: {
|
|
269
|
+
hash: "46192e59d42f741c761cbea79462a8b3815dd905",
|
|
270
|
+
width: 1024,
|
|
271
|
+
height: 1024
|
|
272
|
+
},
|
|
273
|
+
angular: {
|
|
274
|
+
hash: "f31a6c3e94420f43c0cd323a5a6a99376ee59ff8",
|
|
275
|
+
width: 1024,
|
|
276
|
+
height: 1024,
|
|
277
|
+
gridSize: 6
|
|
278
|
+
},
|
|
279
|
+
// Wide format variations
|
|
280
|
+
banner: {
|
|
281
|
+
hash: "d847ffd4269b22c54d6e85ad3c1892a298e961fb",
|
|
282
|
+
width: 1920,
|
|
283
|
+
height: 480,
|
|
284
|
+
gridSize: 8,
|
|
285
|
+
shapesPerLayer: 40
|
|
286
|
+
},
|
|
287
|
+
ultrawide: {
|
|
288
|
+
hash: "a3e126e537ed2cd11ddf3a96c37066e97c7afee6",
|
|
289
|
+
width: 3440,
|
|
290
|
+
height: 1440,
|
|
291
|
+
gridSize: 12,
|
|
292
|
+
shapesPerLayer: 60
|
|
293
|
+
},
|
|
294
|
+
// Social media sizes
|
|
295
|
+
"instagram-square": {
|
|
296
|
+
hash: "ff00ff00ff00ff00ff00ff00ff00ff00ff00ff0",
|
|
297
|
+
width: 1080,
|
|
298
|
+
height: 1080
|
|
299
|
+
},
|
|
300
|
+
"instagram-story": {
|
|
301
|
+
hash: "abc123def456abc123def456abc123def456abc1",
|
|
302
|
+
width: 1080,
|
|
303
|
+
height: 1920,
|
|
304
|
+
gridSize: 6,
|
|
305
|
+
layers: 6
|
|
306
|
+
},
|
|
307
|
+
"twitter-header": {
|
|
308
|
+
hash: "7777777777777777777777777777777777777777",
|
|
309
|
+
width: 1500,
|
|
310
|
+
height: 500,
|
|
311
|
+
gridSize: 8,
|
|
312
|
+
shapesPerLayer: 35
|
|
313
|
+
},
|
|
314
|
+
"linkedin-banner": {
|
|
315
|
+
hash: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
|
|
316
|
+
width: 1584,
|
|
317
|
+
height: 396,
|
|
318
|
+
gridSize: 8,
|
|
319
|
+
shapesPerLayer: 35
|
|
320
|
+
},
|
|
321
|
+
// Mobile sizes
|
|
322
|
+
"phone-wallpaper": {
|
|
323
|
+
hash: "ffffffffffffffffffffffffffffffffaaaaaaaa",
|
|
324
|
+
width: 1170,
|
|
325
|
+
height: 2532,
|
|
326
|
+
gridSize: 5,
|
|
327
|
+
layers: 6
|
|
328
|
+
},
|
|
329
|
+
"tablet-wallpaper": {
|
|
330
|
+
hash: "123456789abcdef0123456789abcdef012345678",
|
|
331
|
+
width: 2048,
|
|
332
|
+
height: 2732,
|
|
333
|
+
gridSize: 7,
|
|
334
|
+
layers: 6
|
|
335
|
+
},
|
|
336
|
+
// Special configurations
|
|
337
|
+
minimal: {
|
|
338
|
+
hash: "000000000000000000000000000000000fffffff",
|
|
339
|
+
width: 1024,
|
|
340
|
+
height: 1024,
|
|
341
|
+
layers: 3,
|
|
342
|
+
baseOpacity: 0.8,
|
|
343
|
+
shapesPerLayer: 15
|
|
344
|
+
},
|
|
345
|
+
complex: {
|
|
346
|
+
hash: "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef",
|
|
347
|
+
width: 2048,
|
|
348
|
+
height: 2048,
|
|
349
|
+
gridSize: 8,
|
|
350
|
+
layers: 7,
|
|
351
|
+
shapesPerLayer: 50,
|
|
352
|
+
minShapeSize: 30,
|
|
353
|
+
maxShapeSize: 250
|
|
354
|
+
}
|
|
355
|
+
};
|
|
356
|
+
const $e0ea14d2e2f06463$export$3572305709b6b48c = {
|
|
357
|
+
strokeStyle: "#000000",
|
|
358
|
+
fillStyle: "transparent",
|
|
359
|
+
lineWidth: 1,
|
|
360
|
+
rotation: 0,
|
|
361
|
+
iterations: 1,
|
|
362
|
+
animate: false
|
|
363
|
+
};
|
|
364
|
+
const $e0ea14d2e2f06463$export$a4ca1369b6d2c19e = {
|
|
365
|
+
BASIC: "basic",
|
|
366
|
+
DETAILED: "detailed",
|
|
367
|
+
ANIMATED: "animated"
|
|
368
|
+
};
|
|
369
|
+
const $e0ea14d2e2f06463$export$bb9e4790bc99ae59 = {
|
|
370
|
+
GOLDEN_RATIO: 1.618034,
|
|
371
|
+
SQUARE_ROOT_2: Math.sqrt(2),
|
|
372
|
+
SQUARE_ROOT_3: Math.sqrt(3),
|
|
373
|
+
SQUARE_ROOT_5: Math.sqrt(5),
|
|
374
|
+
PI: Math.PI,
|
|
375
|
+
PHI: (1 + Math.sqrt(5)) / 2
|
|
376
|
+
};
|
|
377
|
+
const $e0ea14d2e2f06463$export$c36defeab44ba3b3 = {
|
|
378
|
+
flowerOfLifeMandala: (size)=>[
|
|
379
|
+
// { type: "flowerOfLife", config: { size } },
|
|
380
|
+
{
|
|
381
|
+
type: "merkaba",
|
|
382
|
+
config: {
|
|
383
|
+
size: size * 0.8
|
|
384
|
+
}
|
|
385
|
+
},
|
|
386
|
+
{
|
|
387
|
+
type: "sriYantra",
|
|
388
|
+
config: {
|
|
389
|
+
size: size * 0.5
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
],
|
|
393
|
+
platonicProgression: (size)=>[
|
|
394
|
+
{
|
|
395
|
+
type: "platonicSolid",
|
|
396
|
+
config: {
|
|
397
|
+
size: size,
|
|
398
|
+
type: "tetrahedron"
|
|
399
|
+
}
|
|
400
|
+
},
|
|
401
|
+
{
|
|
402
|
+
type: "platonicSolid",
|
|
403
|
+
config: {
|
|
404
|
+
size: size * 0.8,
|
|
405
|
+
type: "cube"
|
|
406
|
+
}
|
|
407
|
+
},
|
|
408
|
+
{
|
|
409
|
+
type: "platonicSolid",
|
|
410
|
+
config: {
|
|
411
|
+
size: size * 0.6,
|
|
412
|
+
type: "octahedron"
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
],
|
|
416
|
+
cosmicTree: (size)=>[
|
|
417
|
+
// { type: "treeOfLife", config: { size } },
|
|
418
|
+
{
|
|
419
|
+
type: "fibonacciSpiral",
|
|
420
|
+
config: {
|
|
421
|
+
size: size * 0.9
|
|
422
|
+
}
|
|
423
|
+
},
|
|
424
|
+
{
|
|
425
|
+
type: "metatronsCube",
|
|
426
|
+
config: {
|
|
427
|
+
size: size * 0.7
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
]
|
|
431
|
+
};
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
const $ce2c52df8af02e62$export$e6bfdeff8bfc94f9 = (degrees)=>degrees * Math.PI / 180;
|
|
435
|
+
const $ce2c52df8af02e62$export$e46c5570db033611 = (ctx, size, config)=>{
|
|
436
|
+
ctx.save();
|
|
437
|
+
ctx.translate(0, 0);
|
|
438
|
+
if (config.rotation) ctx.rotate($ce2c52df8af02e62$export$e6bfdeff8bfc94f9(config.rotation));
|
|
439
|
+
ctx.lineWidth = config.lineWidth;
|
|
440
|
+
ctx.strokeStyle = config.strokeStyle;
|
|
441
|
+
ctx.fillStyle = config.fillStyle;
|
|
442
|
+
};
|
|
443
|
+
const $ce2c52df8af02e62$export$68ae68d395d27fd1 = (ctx)=>{
|
|
444
|
+
ctx.restore();
|
|
445
|
+
};
|
|
446
|
+
const $ce2c52df8af02e62$export$70ba51ca253810ef = (type)=>({
|
|
447
|
+
enabled: false,
|
|
448
|
+
duration: 1000,
|
|
449
|
+
easing: "linear",
|
|
450
|
+
type: type
|
|
451
|
+
});
|
|
452
|
+
const $ce2c52df8af02e62$export$5627764dc1e1d74a = (cx, cy, radius, segments)=>{
|
|
453
|
+
const points = [];
|
|
454
|
+
for(let i = 0; i < segments; i++){
|
|
455
|
+
const angle = i / segments * Math.PI * 2;
|
|
456
|
+
points.push({
|
|
457
|
+
x: cx + Math.cos(angle) * radius,
|
|
458
|
+
y: cy + Math.sin(angle) * radius
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
return points;
|
|
462
|
+
};
|
|
463
|
+
|
|
464
|
+
|
|
465
|
+
const $f0f1a7293548e501$export$90cc629a1c6121c7 = {
|
|
466
|
+
platonic: {
|
|
467
|
+
tetrahedron: {
|
|
468
|
+
vertices: 4,
|
|
469
|
+
faces: 4
|
|
470
|
+
},
|
|
471
|
+
cube: {
|
|
472
|
+
vertices: 8,
|
|
473
|
+
faces: 6
|
|
474
|
+
},
|
|
475
|
+
octahedron: {
|
|
476
|
+
vertices: 6,
|
|
477
|
+
faces: 8
|
|
478
|
+
},
|
|
479
|
+
dodecahedron: {
|
|
480
|
+
vertices: 20,
|
|
481
|
+
faces: 12
|
|
482
|
+
},
|
|
483
|
+
icosahedron: {
|
|
484
|
+
vertices: 12,
|
|
485
|
+
faces: 20
|
|
486
|
+
}
|
|
487
|
+
},
|
|
488
|
+
fibonacci: {
|
|
489
|
+
iterations: 13,
|
|
490
|
+
growthFactor: 1.618034
|
|
491
|
+
},
|
|
492
|
+
goldenRatio: {
|
|
493
|
+
iterations: 8,
|
|
494
|
+
ratio: 1.618034
|
|
495
|
+
}
|
|
496
|
+
};
|
|
497
|
+
const $f0f1a7293548e501$export$4721fcae39954914 = (ctx, size, config = {})=>{
|
|
498
|
+
const finalConfig = {
|
|
499
|
+
...(0, $e0ea14d2e2f06463$export$3572305709b6b48c),
|
|
500
|
+
...config
|
|
501
|
+
};
|
|
502
|
+
(0, $ce2c52df8af02e62$export$e46c5570db033611)(ctx, size, finalConfig);
|
|
503
|
+
const solidType = config.type;
|
|
504
|
+
const solidConfig = $f0f1a7293548e501$export$90cc629a1c6121c7.platonic[solidType] ?? $f0f1a7293548e501$export$90cc629a1c6121c7.platonic.icosahedron;
|
|
505
|
+
const { vertices: vertices } = solidConfig;
|
|
506
|
+
const radius = size / 2;
|
|
507
|
+
// Calculate vertices based on platonic solid type
|
|
508
|
+
const points = (0, $ce2c52df8af02e62$export$5627764dc1e1d74a)(0, 0, radius, vertices);
|
|
509
|
+
ctx.beginPath();
|
|
510
|
+
// Draw edges between vertices
|
|
511
|
+
points.forEach((p1, i)=>{
|
|
512
|
+
points.slice(i + 1).forEach((p2)=>{
|
|
513
|
+
ctx.moveTo(p1.x, p1.y);
|
|
514
|
+
ctx.lineTo(p2.x, p2.y);
|
|
515
|
+
});
|
|
516
|
+
});
|
|
517
|
+
if (finalConfig.fillStyle !== "transparent") ctx.fill();
|
|
518
|
+
ctx.stroke();
|
|
519
|
+
(0, $ce2c52df8af02e62$export$68ae68d395d27fd1)(ctx);
|
|
520
|
+
};
|
|
521
|
+
const $f0f1a7293548e501$export$4091fa94ab006097 = (ctx, size, config = {})=>{
|
|
522
|
+
const finalConfig = {
|
|
523
|
+
...(0, $e0ea14d2e2f06463$export$3572305709b6b48c),
|
|
524
|
+
...$f0f1a7293548e501$export$90cc629a1c6121c7.fibonacci,
|
|
525
|
+
...config
|
|
526
|
+
};
|
|
527
|
+
(0, $ce2c52df8af02e62$export$e46c5570db033611)(ctx, size, finalConfig);
|
|
528
|
+
let current = 1;
|
|
529
|
+
let previous = 1;
|
|
530
|
+
let scale = size / Math.pow(finalConfig.growthFactor, finalConfig.iterations);
|
|
531
|
+
ctx.beginPath();
|
|
532
|
+
for(let i = 0; i < finalConfig.iterations; i++){
|
|
533
|
+
const radius = scale * current;
|
|
534
|
+
const centerX = radius / 2;
|
|
535
|
+
const centerY = radius / 2;
|
|
536
|
+
ctx.arc(centerX, centerY, radius, Math.PI, Math.PI * 1.5);
|
|
537
|
+
// Calculate next Fibonacci number
|
|
538
|
+
const next = current + previous;
|
|
539
|
+
previous = current;
|
|
540
|
+
current = next;
|
|
541
|
+
// Transform for next iteration
|
|
542
|
+
ctx.translate(radius, 0);
|
|
543
|
+
ctx.rotate(Math.PI / 2);
|
|
544
|
+
}
|
|
545
|
+
ctx.stroke();
|
|
546
|
+
(0, $ce2c52df8af02e62$export$68ae68d395d27fd1)(ctx);
|
|
547
|
+
};
|
|
548
|
+
const $f0f1a7293548e501$export$c9043b89bcb14ed9 = (ctx, size, config = {})=>{
|
|
549
|
+
const finalConfig = {
|
|
550
|
+
...(0, $e0ea14d2e2f06463$export$3572305709b6b48c),
|
|
551
|
+
...config
|
|
552
|
+
};
|
|
553
|
+
(0, $ce2c52df8af02e62$export$e46c5570db033611)(ctx, size, finalConfig);
|
|
554
|
+
const gridSize = 8;
|
|
555
|
+
const unit = size / gridSize;
|
|
556
|
+
ctx.beginPath();
|
|
557
|
+
// Create base grid
|
|
558
|
+
for(let i = 0; i <= gridSize; i++)for(let j = 0; j <= gridSize; j++){
|
|
559
|
+
const x = (i - gridSize / 2) * unit;
|
|
560
|
+
const y = (j - gridSize / 2) * unit;
|
|
561
|
+
// Draw star pattern at each intersection
|
|
562
|
+
const radius = unit / 2;
|
|
563
|
+
for(let k = 0; k < 8; k++){
|
|
564
|
+
const angle = Math.PI / 4 * k;
|
|
565
|
+
const x1 = x + radius * Math.cos(angle);
|
|
566
|
+
const y1 = y + radius * Math.sin(angle);
|
|
567
|
+
const x2 = x + radius * Math.cos(angle + Math.PI / 4);
|
|
568
|
+
const y2 = y + radius * Math.sin(angle + Math.PI / 4);
|
|
569
|
+
ctx.moveTo(x1, y1);
|
|
570
|
+
ctx.lineTo(x2, y2);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
ctx.stroke();
|
|
574
|
+
(0, $ce2c52df8af02e62$export$68ae68d395d27fd1)(ctx);
|
|
575
|
+
};
|
|
576
|
+
const $f0f1a7293548e501$export$16ea6f9310920305 = (ctx, size, config = {})=>{
|
|
577
|
+
const finalConfig = {
|
|
578
|
+
...(0, $e0ea14d2e2f06463$export$3572305709b6b48c),
|
|
579
|
+
...config
|
|
580
|
+
};
|
|
581
|
+
(0, $ce2c52df8af02e62$export$e46c5570db033611)(ctx, size, finalConfig);
|
|
582
|
+
const gridSize = 4;
|
|
583
|
+
const unit = size / gridSize;
|
|
584
|
+
const drawKnotSegment = (x, y, type)=>{
|
|
585
|
+
ctx.beginPath();
|
|
586
|
+
switch(type){
|
|
587
|
+
case "over":
|
|
588
|
+
ctx.moveTo(x, y);
|
|
589
|
+
ctx.bezierCurveTo(x + unit / 2, y, x + unit / 2, y + unit, x + unit, y + unit);
|
|
590
|
+
break;
|
|
591
|
+
case "under":
|
|
592
|
+
ctx.moveTo(x, y + unit);
|
|
593
|
+
ctx.bezierCurveTo(x + unit / 2, y + unit, x + unit / 2, y, x + unit, y);
|
|
594
|
+
break;
|
|
595
|
+
}
|
|
596
|
+
ctx.stroke();
|
|
597
|
+
};
|
|
598
|
+
// Create knot pattern
|
|
599
|
+
for(let i = 0; i < gridSize; i++)for(let j = 0; j < gridSize; j++){
|
|
600
|
+
const x = (i - gridSize / 2) * unit;
|
|
601
|
+
const y = (j - gridSize / 2) * unit;
|
|
602
|
+
drawKnotSegment(x, y, (i + j) % 2 === 0 ? "over" : "under");
|
|
603
|
+
}
|
|
604
|
+
(0, $ce2c52df8af02e62$export$68ae68d395d27fd1)(ctx);
|
|
605
|
+
};
|
|
606
|
+
const $f0f1a7293548e501$export$661ad3ddfb8912ed = (ctx, size, config = {})=>{
|
|
607
|
+
const finalConfig = {
|
|
608
|
+
...(0, $e0ea14d2e2f06463$export$3572305709b6b48c),
|
|
609
|
+
...config
|
|
610
|
+
};
|
|
611
|
+
(0, $ce2c52df8af02e62$export$e46c5570db033611)(ctx, size, finalConfig);
|
|
612
|
+
const radius = size / 2;
|
|
613
|
+
// Draw two intersecting tetrahedra
|
|
614
|
+
ctx.beginPath();
|
|
615
|
+
// First tetrahedron
|
|
616
|
+
const points1 = (0, $ce2c52df8af02e62$export$5627764dc1e1d74a)(0, 0, radius, 3);
|
|
617
|
+
points1.forEach((p1, i)=>{
|
|
618
|
+
points1.slice(i + 1).forEach((p2)=>{
|
|
619
|
+
ctx.moveTo(p1.x, p1.y);
|
|
620
|
+
ctx.lineTo(p2.x, p2.y);
|
|
621
|
+
});
|
|
622
|
+
});
|
|
623
|
+
// Second tetrahedron (rotated)
|
|
624
|
+
ctx.rotate(Math.PI / 6);
|
|
625
|
+
const points2 = (0, $ce2c52df8af02e62$export$5627764dc1e1d74a)(0, 0, radius, 3);
|
|
626
|
+
points2.forEach((p1, i)=>{
|
|
627
|
+
points2.slice(i + 1).forEach((p2)=>{
|
|
628
|
+
ctx.moveTo(p1.x, p1.y);
|
|
629
|
+
ctx.lineTo(p2.x, p2.y);
|
|
630
|
+
});
|
|
631
|
+
});
|
|
632
|
+
if (finalConfig.fillStyle !== "transparent") ctx.fill();
|
|
633
|
+
ctx.stroke();
|
|
634
|
+
(0, $ce2c52df8af02e62$export$68ae68d395d27fd1)(ctx);
|
|
635
|
+
};
|
|
636
|
+
const $f0f1a7293548e501$export$97222779ddee1bfe = (ctx, size, config = {})=>{
|
|
637
|
+
const finalConfig = {
|
|
638
|
+
...(0, $e0ea14d2e2f06463$export$3572305709b6b48c),
|
|
639
|
+
...config
|
|
640
|
+
};
|
|
641
|
+
(0, $ce2c52df8af02e62$export$e46c5570db033611)(ctx, size, finalConfig);
|
|
642
|
+
const numCircles = 8;
|
|
643
|
+
const numPoints = 16;
|
|
644
|
+
const radius = size / 2;
|
|
645
|
+
ctx.beginPath();
|
|
646
|
+
for(let i = 1; i <= numCircles; i++){
|
|
647
|
+
const circleRadius = radius / numCircles * i;
|
|
648
|
+
ctx.moveTo(circleRadius, 0);
|
|
649
|
+
ctx.arc(0, 0, circleRadius, 0, Math.PI * 2);
|
|
650
|
+
for(let j = 0; j < numPoints; j++){
|
|
651
|
+
const angle = Math.PI * 2 * j / numPoints;
|
|
652
|
+
const x = circleRadius * Math.cos(angle);
|
|
653
|
+
const y = circleRadius * Math.sin(angle);
|
|
654
|
+
ctx.moveTo(0, 0);
|
|
655
|
+
ctx.lineTo(x, y);
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
ctx.stroke();
|
|
659
|
+
(0, $ce2c52df8af02e62$export$68ae68d395d27fd1)(ctx);
|
|
660
|
+
};
|
|
661
|
+
const $f0f1a7293548e501$export$4fab07e71ae4aeeb = (ctx, size, config = {})=>{
|
|
662
|
+
const finalConfig = {
|
|
663
|
+
...(0, $e0ea14d2e2f06463$export$3572305709b6b48c),
|
|
664
|
+
...config,
|
|
665
|
+
iterations: 5
|
|
666
|
+
};
|
|
667
|
+
(0, $ce2c52df8af02e62$export$e46c5570db033611)(ctx, size, finalConfig);
|
|
668
|
+
const drawBranch = (x, y, length, angle, depth)=>{
|
|
669
|
+
if (depth === 0) return;
|
|
670
|
+
const endX = x + length * Math.cos(angle);
|
|
671
|
+
const endY = y + length * Math.sin(angle);
|
|
672
|
+
ctx.beginPath();
|
|
673
|
+
ctx.moveTo(x, y);
|
|
674
|
+
ctx.lineTo(endX, endY);
|
|
675
|
+
ctx.stroke();
|
|
676
|
+
drawBranch(endX, endY, length * 0.7, angle - Math.PI / 6, depth - 1);
|
|
677
|
+
drawBranch(endX, endY, length * 0.7, angle + Math.PI / 6, depth - 1);
|
|
678
|
+
};
|
|
679
|
+
drawBranch(0, size / 2, size / 4, -Math.PI / 2, finalConfig.iterations);
|
|
680
|
+
(0, $ce2c52df8af02e62$export$68ae68d395d27fd1)(ctx);
|
|
681
|
+
};
|
|
682
|
+
const $f0f1a7293548e501$export$dbe318a13ce51887 = {
|
|
683
|
+
platonicSolid: $f0f1a7293548e501$export$4721fcae39954914,
|
|
684
|
+
fibonacciSpiral: $f0f1a7293548e501$export$4091fa94ab006097,
|
|
685
|
+
islamicPattern: $f0f1a7293548e501$export$c9043b89bcb14ed9,
|
|
686
|
+
celticKnot: $f0f1a7293548e501$export$16ea6f9310920305,
|
|
687
|
+
merkaba: $f0f1a7293548e501$export$661ad3ddfb8912ed,
|
|
688
|
+
mandala: $f0f1a7293548e501$export$97222779ddee1bfe,
|
|
689
|
+
fractal: $f0f1a7293548e501$export$4fab07e71ae4aeeb
|
|
690
|
+
};
|
|
691
|
+
|
|
692
|
+
|
|
693
|
+
|
|
694
|
+
const $77711f013715e6da$export$3bac12a72d9de58c = (ctx, size)=>{
|
|
695
|
+
const radius = size / 6;
|
|
696
|
+
const centers = [
|
|
697
|
+
{
|
|
698
|
+
x: 0,
|
|
699
|
+
y: 0
|
|
700
|
+
},
|
|
701
|
+
{
|
|
702
|
+
x: radius * Math.sqrt(3),
|
|
703
|
+
y: 0
|
|
704
|
+
},
|
|
705
|
+
{
|
|
706
|
+
x: radius * Math.sqrt(3) / 2,
|
|
707
|
+
y: 1.5 * radius
|
|
708
|
+
},
|
|
709
|
+
{
|
|
710
|
+
x: -radius * Math.sqrt(3) / 2,
|
|
711
|
+
y: 1.5 * radius
|
|
712
|
+
},
|
|
713
|
+
{
|
|
714
|
+
x: -radius * Math.sqrt(3),
|
|
715
|
+
y: 0
|
|
716
|
+
},
|
|
717
|
+
{
|
|
718
|
+
x: -radius * Math.sqrt(3) / 2,
|
|
719
|
+
y: -1.5 * radius
|
|
720
|
+
},
|
|
721
|
+
{
|
|
722
|
+
x: radius * Math.sqrt(3) / 2,
|
|
723
|
+
y: -1.5 * radius
|
|
724
|
+
}
|
|
725
|
+
];
|
|
726
|
+
ctx.beginPath();
|
|
727
|
+
centers.forEach((center)=>{
|
|
728
|
+
ctx.moveTo(center.x + radius, center.y);
|
|
729
|
+
ctx.arc(center.x, center.y, radius, 0, Math.PI * 2);
|
|
730
|
+
});
|
|
731
|
+
};
|
|
732
|
+
const $77711f013715e6da$export$639bf214428ceec2 = (ctx, size)=>{
|
|
733
|
+
const radius = size / 12;
|
|
734
|
+
const spacing = radius * 2.5;
|
|
735
|
+
// Sephirot positions (traditional layout)
|
|
736
|
+
const positions = [
|
|
737
|
+
{
|
|
738
|
+
x: 0,
|
|
739
|
+
y: -spacing * 2
|
|
740
|
+
},
|
|
741
|
+
{
|
|
742
|
+
x: -spacing,
|
|
743
|
+
y: -spacing
|
|
744
|
+
},
|
|
745
|
+
{
|
|
746
|
+
x: spacing,
|
|
747
|
+
y: -spacing
|
|
748
|
+
},
|
|
749
|
+
{
|
|
750
|
+
x: -spacing,
|
|
751
|
+
y: 0
|
|
752
|
+
},
|
|
753
|
+
{
|
|
754
|
+
x: spacing,
|
|
755
|
+
y: 0
|
|
756
|
+
},
|
|
757
|
+
{
|
|
758
|
+
x: 0,
|
|
759
|
+
y: 0
|
|
760
|
+
},
|
|
761
|
+
{
|
|
762
|
+
x: -spacing,
|
|
763
|
+
y: spacing
|
|
764
|
+
},
|
|
765
|
+
{
|
|
766
|
+
x: spacing,
|
|
767
|
+
y: spacing
|
|
768
|
+
},
|
|
769
|
+
{
|
|
770
|
+
x: 0,
|
|
771
|
+
y: spacing * 2
|
|
772
|
+
},
|
|
773
|
+
{
|
|
774
|
+
x: 0,
|
|
775
|
+
y: spacing * 3
|
|
776
|
+
}
|
|
777
|
+
];
|
|
778
|
+
// Draw circles
|
|
779
|
+
ctx.beginPath();
|
|
780
|
+
positions.forEach((pos)=>{
|
|
781
|
+
ctx.moveTo(pos.x + radius, pos.y);
|
|
782
|
+
ctx.arc(pos.x, pos.y, radius, 0, Math.PI * 2);
|
|
783
|
+
});
|
|
784
|
+
// Draw connecting lines
|
|
785
|
+
ctx.moveTo(positions[0].x, positions[0].y);
|
|
786
|
+
positions.forEach((pos, i)=>{
|
|
787
|
+
if (i > 0) positions.slice(i + 1).forEach((nextPos)=>{
|
|
788
|
+
ctx.moveTo(pos.x, pos.y);
|
|
789
|
+
ctx.lineTo(nextPos.x, nextPos.y);
|
|
790
|
+
});
|
|
791
|
+
});
|
|
792
|
+
};
|
|
793
|
+
const $77711f013715e6da$export$de26673ceb3e04eb = (ctx, size)=>{
|
|
794
|
+
const radius = size / 3;
|
|
795
|
+
// Create 13 points - one center and 12 vertices of an icosahedron
|
|
796
|
+
// const phi = (1 + Math.sqrt(5)) / 2; // Golden ratio
|
|
797
|
+
const vertices = [
|
|
798
|
+
{
|
|
799
|
+
x: 0,
|
|
800
|
+
y: 0
|
|
801
|
+
},
|
|
802
|
+
...(0, $ce2c52df8af02e62$export$5627764dc1e1d74a)(0, 0, radius, 6),
|
|
803
|
+
...(0, $ce2c52df8af02e62$export$5627764dc1e1d74a)(0, 0, radius * 1.5, 6)
|
|
804
|
+
];
|
|
805
|
+
ctx.beginPath();
|
|
806
|
+
// Draw all connecting lines
|
|
807
|
+
vertices.forEach((v1, i)=>{
|
|
808
|
+
vertices.slice(i + 1).forEach((v2)=>{
|
|
809
|
+
ctx.moveTo(v1.x, v1.y);
|
|
810
|
+
ctx.lineTo(v2.x, v2.y);
|
|
811
|
+
});
|
|
812
|
+
});
|
|
813
|
+
};
|
|
814
|
+
const $77711f013715e6da$export$f743702d1590aefb = (ctx, size)=>{
|
|
815
|
+
const radius = size / 2;
|
|
816
|
+
ctx.beginPath();
|
|
817
|
+
// Draw outer triangles
|
|
818
|
+
for(let i = 0; i < 9; i++){
|
|
819
|
+
const angle = i / 9 * Math.PI * 2;
|
|
820
|
+
const x1 = Math.cos(angle) * radius;
|
|
821
|
+
const y1 = Math.sin(angle) * radius;
|
|
822
|
+
const x2 = Math.cos(angle + Math.PI / 9) * radius;
|
|
823
|
+
const y2 = Math.sin(angle + Math.PI / 9) * radius;
|
|
824
|
+
ctx.moveTo(0, 0);
|
|
825
|
+
ctx.lineTo(x1, y1);
|
|
826
|
+
ctx.lineTo(x2, y2);
|
|
827
|
+
ctx.lineTo(0, 0);
|
|
828
|
+
}
|
|
829
|
+
// Draw inner triangles
|
|
830
|
+
const innerRadius = radius * 0.6;
|
|
831
|
+
for(let i = 0; i < 9; i++){
|
|
832
|
+
const angle = i / 9 * Math.PI * 2 + Math.PI / 18;
|
|
833
|
+
const x1 = Math.cos(angle) * innerRadius;
|
|
834
|
+
const y1 = Math.sin(angle) * innerRadius;
|
|
835
|
+
const x2 = Math.cos(angle + Math.PI / 9) * innerRadius;
|
|
836
|
+
const y2 = Math.sin(angle + Math.PI / 9) * innerRadius;
|
|
837
|
+
ctx.moveTo(0, 0);
|
|
838
|
+
ctx.lineTo(x1, y1);
|
|
839
|
+
ctx.lineTo(x2, y2);
|
|
840
|
+
ctx.lineTo(0, 0);
|
|
841
|
+
}
|
|
842
|
+
};
|
|
843
|
+
const $77711f013715e6da$export$980631444e370ab0 = (ctx, size)=>{
|
|
844
|
+
const radius = size / 6;
|
|
845
|
+
const centers = [
|
|
846
|
+
{
|
|
847
|
+
x: 0,
|
|
848
|
+
y: 0
|
|
849
|
+
},
|
|
850
|
+
{
|
|
851
|
+
x: radius * Math.sqrt(3),
|
|
852
|
+
y: 0
|
|
853
|
+
},
|
|
854
|
+
{
|
|
855
|
+
x: radius * Math.sqrt(3) / 2,
|
|
856
|
+
y: 1.5 * radius
|
|
857
|
+
},
|
|
858
|
+
{
|
|
859
|
+
x: -radius * Math.sqrt(3) / 2,
|
|
860
|
+
y: 1.5 * radius
|
|
861
|
+
},
|
|
862
|
+
{
|
|
863
|
+
x: -radius * Math.sqrt(3),
|
|
864
|
+
y: 0
|
|
865
|
+
},
|
|
866
|
+
{
|
|
867
|
+
x: -radius * Math.sqrt(3) / 2,
|
|
868
|
+
y: -1.5 * radius
|
|
869
|
+
},
|
|
870
|
+
{
|
|
871
|
+
x: radius * Math.sqrt(3) / 2,
|
|
872
|
+
y: -1.5 * radius
|
|
873
|
+
}
|
|
874
|
+
];
|
|
875
|
+
ctx.beginPath();
|
|
876
|
+
centers.forEach((center)=>{
|
|
877
|
+
ctx.moveTo(center.x + radius, center.y);
|
|
878
|
+
ctx.arc(center.x, center.y, radius, 0, Math.PI * 2);
|
|
879
|
+
});
|
|
880
|
+
};
|
|
881
|
+
const $77711f013715e6da$export$eeae7765f05012e2 = (ctx, size)=>{
|
|
882
|
+
const radius = size / 4;
|
|
883
|
+
ctx.beginPath();
|
|
884
|
+
ctx.arc(-radius / 2, 0, radius, 0, Math.PI * 2);
|
|
885
|
+
ctx.arc(radius / 2, 0, radius, 0, Math.PI * 2);
|
|
886
|
+
};
|
|
887
|
+
const $77711f013715e6da$export$3355220a8108efc3 = (ctx, size)=>{
|
|
888
|
+
const outerRadius = size / 2;
|
|
889
|
+
const innerRadius = size / 4;
|
|
890
|
+
const steps = 36;
|
|
891
|
+
ctx.beginPath();
|
|
892
|
+
for(let i = 0; i < steps; i++){
|
|
893
|
+
const angle1 = i / steps * Math.PI * 2;
|
|
894
|
+
// const angle2 = ((i + 1) / steps) * Math.PI * 2;
|
|
895
|
+
for(let j = 0; j < steps; j++){
|
|
896
|
+
const phi1 = j / steps * Math.PI * 2;
|
|
897
|
+
const phi2 = (j + 1) / steps * Math.PI * 2;
|
|
898
|
+
const x1 = (outerRadius + innerRadius * Math.cos(phi1)) * Math.cos(angle1);
|
|
899
|
+
const y1 = (outerRadius + innerRadius * Math.cos(phi1)) * Math.sin(angle1);
|
|
900
|
+
const x2 = (outerRadius + innerRadius * Math.cos(phi2)) * Math.cos(angle1);
|
|
901
|
+
const y2 = (outerRadius + innerRadius * Math.cos(phi2)) * Math.sin(angle1);
|
|
902
|
+
ctx.moveTo(x1, y1);
|
|
903
|
+
ctx.lineTo(x2, y2);
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
};
|
|
907
|
+
const $77711f013715e6da$export$31e39e0544d9b1e8 = (ctx, size)=>{
|
|
908
|
+
const radius = size / 8;
|
|
909
|
+
const centers = [
|
|
910
|
+
{
|
|
911
|
+
x: 0,
|
|
912
|
+
y: 0
|
|
913
|
+
},
|
|
914
|
+
{
|
|
915
|
+
x: radius * 2,
|
|
916
|
+
y: 0
|
|
917
|
+
},
|
|
918
|
+
{
|
|
919
|
+
x: radius,
|
|
920
|
+
y: radius * Math.sqrt(3)
|
|
921
|
+
},
|
|
922
|
+
{
|
|
923
|
+
x: -radius,
|
|
924
|
+
y: radius * Math.sqrt(3)
|
|
925
|
+
},
|
|
926
|
+
{
|
|
927
|
+
x: -radius * 2,
|
|
928
|
+
y: 0
|
|
929
|
+
},
|
|
930
|
+
{
|
|
931
|
+
x: -radius,
|
|
932
|
+
y: -radius * Math.sqrt(3)
|
|
933
|
+
},
|
|
934
|
+
{
|
|
935
|
+
x: radius,
|
|
936
|
+
y: -radius * Math.sqrt(3)
|
|
937
|
+
}
|
|
938
|
+
];
|
|
939
|
+
ctx.beginPath();
|
|
940
|
+
centers.forEach((center)=>{
|
|
941
|
+
ctx.moveTo(center.x + radius, center.y);
|
|
942
|
+
ctx.arc(center.x, center.y, radius, 0, Math.PI * 2);
|
|
943
|
+
});
|
|
944
|
+
};
|
|
945
|
+
const $77711f013715e6da$export$c2fc138f94dd4b2a = {
|
|
946
|
+
flowerOfLife: $77711f013715e6da$export$3bac12a72d9de58c,
|
|
947
|
+
treeOfLife: $77711f013715e6da$export$639bf214428ceec2,
|
|
948
|
+
metatronsCube: $77711f013715e6da$export$de26673ceb3e04eb,
|
|
949
|
+
sriYantra: $77711f013715e6da$export$f743702d1590aefb,
|
|
950
|
+
seedOfLife: $77711f013715e6da$export$980631444e370ab0,
|
|
951
|
+
vesicaPiscis: $77711f013715e6da$export$eeae7765f05012e2,
|
|
952
|
+
torus: $77711f013715e6da$export$3355220a8108efc3,
|
|
953
|
+
eggOfLife: $77711f013715e6da$export$31e39e0544d9b1e8
|
|
954
|
+
};
|
|
955
|
+
|
|
956
|
+
|
|
957
|
+
const $e41b41d8dcf837ad$export$4ff7fc6f1af248b5 = {
|
|
958
|
+
...(0, $44f5b87a40c9680b$export$492753207a5258e1),
|
|
959
|
+
...(0, $f0f1a7293548e501$export$dbe318a13ce51887),
|
|
960
|
+
...(0, $77711f013715e6da$export$c2fc138f94dd4b2a)
|
|
961
|
+
};
|
|
962
|
+
|
|
963
|
+
|
|
964
|
+
function $e0f99502ff383dd8$export$71b514a25c47df50(ctx, shape, x, y, config) {
|
|
965
|
+
const { fillColor: fillColor, strokeColor: strokeColor, strokeWidth: strokeWidth, size: size, rotation: rotation } = config;
|
|
966
|
+
ctx.save();
|
|
967
|
+
ctx.translate(x, y);
|
|
968
|
+
ctx.rotate(rotation * Math.PI / 180);
|
|
969
|
+
ctx.fillStyle = fillColor;
|
|
970
|
+
ctx.strokeStyle = strokeColor;
|
|
971
|
+
ctx.lineWidth = strokeWidth;
|
|
972
|
+
const drawFunction = (0, $e41b41d8dcf837ad$export$4ff7fc6f1af248b5)[shape];
|
|
973
|
+
if (drawFunction) {
|
|
974
|
+
drawFunction(ctx, size);
|
|
975
|
+
ctx.fill();
|
|
976
|
+
ctx.stroke();
|
|
977
|
+
}
|
|
978
|
+
ctx.restore();
|
|
979
|
+
}
|
|
980
|
+
function $e0f99502ff383dd8$export$bb35a6995ddbf32d(ctx, shape, x, y, config) {
|
|
981
|
+
const { fillColor: fillColor, strokeColor: strokeColor, strokeWidth: strokeWidth, size: size, rotation: rotation, patterns: patterns = [], proportionType: proportionType = "GOLDEN_RATIO", baseOpacity: baseOpacity = 0.6, opacityReduction: opacityReduction = 0.1, glowRadius: glowRadius = 0, glowColor: glowColor, gradientFillEnd: gradientFillEnd } = config;
|
|
982
|
+
ctx.save();
|
|
983
|
+
ctx.translate(x, y);
|
|
984
|
+
ctx.rotate(rotation * Math.PI / 180);
|
|
985
|
+
// Glow / shadow effect
|
|
986
|
+
if (glowRadius > 0) {
|
|
987
|
+
ctx.shadowBlur = glowRadius;
|
|
988
|
+
ctx.shadowColor = glowColor || fillColor;
|
|
989
|
+
ctx.shadowOffsetX = 0;
|
|
990
|
+
ctx.shadowOffsetY = 0;
|
|
991
|
+
}
|
|
992
|
+
// Gradient fill or flat fill
|
|
993
|
+
if (gradientFillEnd) {
|
|
994
|
+
const grad = ctx.createRadialGradient(0, 0, 0, 0, 0, size / 2);
|
|
995
|
+
grad.addColorStop(0, fillColor);
|
|
996
|
+
grad.addColorStop(1, gradientFillEnd);
|
|
997
|
+
ctx.fillStyle = grad;
|
|
998
|
+
} else ctx.fillStyle = fillColor;
|
|
999
|
+
ctx.strokeStyle = strokeColor;
|
|
1000
|
+
ctx.lineWidth = strokeWidth;
|
|
1001
|
+
const drawFunction = (0, $e41b41d8dcf837ad$export$4ff7fc6f1af248b5)[shape];
|
|
1002
|
+
if (drawFunction) {
|
|
1003
|
+
drawFunction(ctx, size);
|
|
1004
|
+
ctx.fill();
|
|
1005
|
+
ctx.stroke();
|
|
1006
|
+
}
|
|
1007
|
+
// Reset shadow so patterns aren't double-glowed
|
|
1008
|
+
if (glowRadius > 0) ctx.shadowBlur = 0;
|
|
1009
|
+
// Layer additional patterns if specified
|
|
1010
|
+
if (patterns.length > 0) (0, $616009579e3d72c5$export$da2372f11bc66b3f).layerPatterns(ctx, patterns, {
|
|
1011
|
+
baseSize: size,
|
|
1012
|
+
baseOpacity: baseOpacity,
|
|
1013
|
+
opacityReduction: opacityReduction,
|
|
1014
|
+
proportionType: proportionType
|
|
1015
|
+
});
|
|
1016
|
+
ctx.restore();
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
|
|
1020
|
+
|
|
1021
|
+
|
|
1022
|
+
/**
|
|
1023
|
+
* Configuration options for image generation.
|
|
1024
|
+
*/ const $81c1b644006d48ec$export$c2f8e0cc249a8d8f = {
|
|
1025
|
+
width: 2048,
|
|
1026
|
+
height: 2048,
|
|
1027
|
+
gridSize: 5,
|
|
1028
|
+
layers: 4,
|
|
1029
|
+
minShapeSize: 30,
|
|
1030
|
+
maxShapeSize: 400,
|
|
1031
|
+
baseOpacity: 0.7,
|
|
1032
|
+
opacityReduction: 0.12,
|
|
1033
|
+
shapesPerLayer: 0
|
|
1034
|
+
};
|
|
1035
|
+
|
|
1036
|
+
|
|
1037
|
+
// ── Shape categories for weighted selection ─────────────────────────
|
|
1038
|
+
const $1f63dc64b5593c73$var$BASIC_SHAPES = [
|
|
1039
|
+
"circle",
|
|
1040
|
+
"square",
|
|
1041
|
+
"triangle",
|
|
1042
|
+
"hexagon",
|
|
1043
|
+
"diamond",
|
|
1044
|
+
"cube"
|
|
1045
|
+
];
|
|
1046
|
+
const $1f63dc64b5593c73$var$COMPLEX_SHAPES = [
|
|
1047
|
+
"star",
|
|
1048
|
+
"jacked-star",
|
|
1049
|
+
"heart",
|
|
1050
|
+
"platonicSolid",
|
|
1051
|
+
"fibonacciSpiral",
|
|
1052
|
+
"islamicPattern",
|
|
1053
|
+
"celticKnot",
|
|
1054
|
+
"merkaba",
|
|
1055
|
+
"fractal"
|
|
1056
|
+
];
|
|
1057
|
+
const $1f63dc64b5593c73$var$SACRED_SHAPES = [
|
|
1058
|
+
"mandala",
|
|
1059
|
+
"flowerOfLife",
|
|
1060
|
+
"treeOfLife",
|
|
1061
|
+
"metatronsCube",
|
|
1062
|
+
"sriYantra",
|
|
1063
|
+
"seedOfLife",
|
|
1064
|
+
"vesicaPiscis",
|
|
1065
|
+
"torus",
|
|
1066
|
+
"eggOfLife"
|
|
1067
|
+
];
|
|
1068
|
+
const $1f63dc64b5593c73$var$COMPOSITION_MODES = [
|
|
1069
|
+
"radial",
|
|
1070
|
+
"flow-field",
|
|
1071
|
+
"spiral",
|
|
1072
|
+
"grid-subdivision",
|
|
1073
|
+
"clustered"
|
|
1074
|
+
];
|
|
1075
|
+
// ── Helper: pick shape with layer-aware weighting ───────────────────
|
|
1076
|
+
function $1f63dc64b5593c73$var$pickShape(rng, layerRatio, shapeNames) {
|
|
1077
|
+
const basicW = 1 - layerRatio * 0.6;
|
|
1078
|
+
const complexW = 0.3 + layerRatio * 0.3;
|
|
1079
|
+
const sacredW = 0.1 + layerRatio * 0.4;
|
|
1080
|
+
const total = basicW + complexW + sacredW;
|
|
1081
|
+
const roll = rng() * total;
|
|
1082
|
+
let pool;
|
|
1083
|
+
if (roll < basicW) pool = $1f63dc64b5593c73$var$BASIC_SHAPES;
|
|
1084
|
+
else if (roll < basicW + complexW) pool = $1f63dc64b5593c73$var$COMPLEX_SHAPES;
|
|
1085
|
+
else pool = $1f63dc64b5593c73$var$SACRED_SHAPES;
|
|
1086
|
+
const available = pool.filter((s)=>shapeNames.includes(s));
|
|
1087
|
+
if (available.length === 0) return shapeNames[Math.floor(rng() * shapeNames.length)];
|
|
1088
|
+
return available[Math.floor(rng() * available.length)];
|
|
1089
|
+
}
|
|
1090
|
+
// ── Helper: simple 2D value noise (hash-seeded) ─────────────────────
|
|
1091
|
+
function $1f63dc64b5593c73$var$valueNoise(x, y, scale, rng) {
|
|
1092
|
+
// Cheap pseudo-noise: combine sin waves at different frequencies
|
|
1093
|
+
const nx = x / scale;
|
|
1094
|
+
const ny = y / scale;
|
|
1095
|
+
return (Math.sin(nx * 1.7 + ny * 2.3 + rng() * 0.001) * 0.5 + Math.sin(nx * 3.1 - ny * 1.9 + rng() * 0.001) * 0.3 + Math.sin(nx * 5.3 + ny * 4.7 + rng() * 0.001) * 0.2) * 0.5 + 0.5;
|
|
1096
|
+
}
|
|
1097
|
+
// ── Helper: get position based on composition mode ──────────────────
|
|
1098
|
+
function $1f63dc64b5593c73$var$getCompositionPosition(mode, rng, width, height, shapeIndex, totalShapes, cx, cy) {
|
|
1099
|
+
switch(mode){
|
|
1100
|
+
case "radial":
|
|
1101
|
+
{
|
|
1102
|
+
const angle = rng() * Math.PI * 2;
|
|
1103
|
+
const maxR = Math.min(width, height) * 0.45;
|
|
1104
|
+
const r = Math.pow(rng(), 0.7) * maxR;
|
|
1105
|
+
return {
|
|
1106
|
+
x: cx + Math.cos(angle) * r,
|
|
1107
|
+
y: cy + Math.sin(angle) * r
|
|
1108
|
+
};
|
|
1109
|
+
}
|
|
1110
|
+
case "spiral":
|
|
1111
|
+
{
|
|
1112
|
+
const t = shapeIndex / totalShapes;
|
|
1113
|
+
const turns = 3 + rng() * 2;
|
|
1114
|
+
const angle = t * Math.PI * 2 * turns;
|
|
1115
|
+
const maxR = Math.min(width, height) * 0.42;
|
|
1116
|
+
const r = t * maxR + (rng() - 0.5) * maxR * 0.15;
|
|
1117
|
+
return {
|
|
1118
|
+
x: cx + Math.cos(angle) * r,
|
|
1119
|
+
y: cy + Math.sin(angle) * r
|
|
1120
|
+
};
|
|
1121
|
+
}
|
|
1122
|
+
case "grid-subdivision":
|
|
1123
|
+
{
|
|
1124
|
+
const cells = 3 + Math.floor(rng() * 3);
|
|
1125
|
+
const cellW = width / cells;
|
|
1126
|
+
const cellH = height / cells;
|
|
1127
|
+
const gx = Math.floor(rng() * cells);
|
|
1128
|
+
const gy = Math.floor(rng() * cells);
|
|
1129
|
+
return {
|
|
1130
|
+
x: gx * cellW + rng() * cellW,
|
|
1131
|
+
y: gy * cellH + rng() * cellH
|
|
1132
|
+
};
|
|
1133
|
+
}
|
|
1134
|
+
case "clustered":
|
|
1135
|
+
{
|
|
1136
|
+
// Pick one of 3-5 cluster centers, then scatter around it
|
|
1137
|
+
const numClusters = 3 + Math.floor(rng() * 3);
|
|
1138
|
+
const ci = Math.floor(rng() * numClusters);
|
|
1139
|
+
// Deterministic cluster center from index
|
|
1140
|
+
const clusterRng = (0, $616009579e3d72c5$export$eaf9227667332084)((0, $616009579e3d72c5$export$e9cc707de01b7042)(String(ci), 999));
|
|
1141
|
+
const clx = width * (0.15 + clusterRng() * 0.7);
|
|
1142
|
+
const cly = height * (0.15 + clusterRng() * 0.7);
|
|
1143
|
+
const spread = Math.min(width, height) * 0.18;
|
|
1144
|
+
return {
|
|
1145
|
+
x: clx + (rng() - 0.5) * spread * 2,
|
|
1146
|
+
y: cly + (rng() - 0.5) * spread * 2
|
|
1147
|
+
};
|
|
1148
|
+
}
|
|
1149
|
+
case "flow-field":
|
|
1150
|
+
default:
|
|
1151
|
+
// Random position, will be adjusted by flow field direction later
|
|
1152
|
+
return {
|
|
1153
|
+
x: rng() * width,
|
|
1154
|
+
y: rng() * height
|
|
1155
|
+
};
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
// ── Helper: positional color blending ───────────────────────────────
|
|
1159
|
+
function $1f63dc64b5593c73$var$getPositionalColor(x, y, width, height, colors, rng) {
|
|
1160
|
+
// Blend between palette colors based on position
|
|
1161
|
+
const nx = x / width;
|
|
1162
|
+
const ny = y / height;
|
|
1163
|
+
// Use position to bias which palette color is chosen
|
|
1164
|
+
const posIndex = (nx * 0.6 + ny * 0.4) * (colors.length - 1);
|
|
1165
|
+
const baseIdx = Math.floor(posIndex) % colors.length;
|
|
1166
|
+
// Then jitter it slightly
|
|
1167
|
+
return (0, $b5a262d09b87e373$export$59539d800dbe6858)(colors[baseIdx], rng, 0.08);
|
|
1168
|
+
}
|
|
1169
|
+
function $1f63dc64b5593c73$export$29a844702096332e(ctx, gitHash, config = {}) {
|
|
1170
|
+
const finalConfig = {
|
|
1171
|
+
...(0, $81c1b644006d48ec$export$c2f8e0cc249a8d8f),
|
|
1172
|
+
...config
|
|
1173
|
+
};
|
|
1174
|
+
const { width: width, height: height, gridSize: gridSize, layers: layers, minShapeSize: minShapeSize, maxShapeSize: maxShapeSize, baseOpacity: baseOpacity, opacityReduction: opacityReduction } = finalConfig;
|
|
1175
|
+
finalConfig.shapesPerLayer = finalConfig.shapesPerLayer || Math.floor(gridSize * gridSize * 1.5);
|
|
1176
|
+
const colorScheme = new (0, $b5a262d09b87e373$export$ab958c550f521376)(gitHash);
|
|
1177
|
+
const colors = colorScheme.getColors();
|
|
1178
|
+
const [bgStart, bgEnd] = colorScheme.getBackgroundColors();
|
|
1179
|
+
const shapeNames = Object.keys((0, $e41b41d8dcf837ad$export$4ff7fc6f1af248b5));
|
|
1180
|
+
const scaleFactor = Math.min(width, height) / 1024;
|
|
1181
|
+
const adjustedMinSize = minShapeSize * scaleFactor;
|
|
1182
|
+
const adjustedMaxSize = maxShapeSize * scaleFactor;
|
|
1183
|
+
const rng = (0, $616009579e3d72c5$export$eaf9227667332084)((0, $616009579e3d72c5$export$e9cc707de01b7042)(gitHash));
|
|
1184
|
+
const cx = width / 2;
|
|
1185
|
+
const cy = height / 2;
|
|
1186
|
+
// ── 1. Background ──────────────────────────────────────────────
|
|
1187
|
+
const bgRadius = Math.hypot(cx, cy);
|
|
1188
|
+
const bgGrad = ctx.createRadialGradient(cx, cy, 0, cx, cy, bgRadius);
|
|
1189
|
+
bgGrad.addColorStop(0, bgStart);
|
|
1190
|
+
bgGrad.addColorStop(1, bgEnd);
|
|
1191
|
+
ctx.fillStyle = bgGrad;
|
|
1192
|
+
ctx.fillRect(0, 0, width, height);
|
|
1193
|
+
// ── 2. Composition mode ────────────────────────────────────────
|
|
1194
|
+
const compositionMode = $1f63dc64b5593c73$var$COMPOSITION_MODES[Math.floor(rng() * $1f63dc64b5593c73$var$COMPOSITION_MODES.length)];
|
|
1195
|
+
// ── 3. Focal points ────────────────────────────────────────────
|
|
1196
|
+
const numFocal = 1 + Math.floor(rng() * 2);
|
|
1197
|
+
const focalPoints = [];
|
|
1198
|
+
for(let f = 0; f < numFocal; f++)focalPoints.push({
|
|
1199
|
+
x: width * (0.2 + rng() * 0.6),
|
|
1200
|
+
y: height * (0.2 + rng() * 0.6),
|
|
1201
|
+
strength: 0.3 + rng() * 0.4
|
|
1202
|
+
});
|
|
1203
|
+
function applyFocalBias(rx, ry) {
|
|
1204
|
+
let nearest = focalPoints[0];
|
|
1205
|
+
let minDist = Infinity;
|
|
1206
|
+
for (const fp of focalPoints){
|
|
1207
|
+
const d = Math.hypot(rx - fp.x, ry - fp.y);
|
|
1208
|
+
if (d < minDist) {
|
|
1209
|
+
minDist = d;
|
|
1210
|
+
nearest = fp;
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
const pull = nearest.strength * rng() * 0.5;
|
|
1214
|
+
return [
|
|
1215
|
+
rx + (nearest.x - rx) * pull,
|
|
1216
|
+
ry + (nearest.y - ry) * pull
|
|
1217
|
+
];
|
|
1218
|
+
}
|
|
1219
|
+
// ── 4. Flow field seed values (for flow-field mode & line pass) ─
|
|
1220
|
+
const fieldAngleBase = rng() * Math.PI * 2;
|
|
1221
|
+
const fieldFreq = 0.5 + rng() * 2;
|
|
1222
|
+
function flowAngle(x, y) {
|
|
1223
|
+
return fieldAngleBase + Math.sin(x / width * fieldFreq * Math.PI * 2) * Math.PI * 0.5 + Math.cos(y / height * fieldFreq * Math.PI * 2) * Math.PI * 0.5;
|
|
1224
|
+
}
|
|
1225
|
+
// ── 5. Shape layers ────────────────────────────────────────────
|
|
1226
|
+
const shapePositions = [];
|
|
1227
|
+
for(let layer = 0; layer < layers; layer++){
|
|
1228
|
+
const layerRatio = layers > 1 ? layer / (layers - 1) : 0;
|
|
1229
|
+
const numShapes = finalConfig.shapesPerLayer + Math.floor(rng() * finalConfig.shapesPerLayer * 0.3);
|
|
1230
|
+
const layerOpacity = Math.max(0.15, baseOpacity - layer * opacityReduction);
|
|
1231
|
+
const layerSizeScale = 1 - layer * 0.15;
|
|
1232
|
+
for(let i = 0; i < numShapes; i++){
|
|
1233
|
+
// Position from composition mode, then focal bias
|
|
1234
|
+
const rawPos = $1f63dc64b5593c73$var$getCompositionPosition(compositionMode, rng, width, height, i, numShapes, cx, cy);
|
|
1235
|
+
const [x, y] = applyFocalBias(rawPos.x, rawPos.y);
|
|
1236
|
+
// Weighted shape selection
|
|
1237
|
+
const shape = $1f63dc64b5593c73$var$pickShape(rng, layerRatio, shapeNames);
|
|
1238
|
+
// Power distribution for size
|
|
1239
|
+
const sizeT = Math.pow(rng(), 1.8);
|
|
1240
|
+
const size = (adjustedMinSize + sizeT * (adjustedMaxSize - adjustedMinSize)) * layerSizeScale;
|
|
1241
|
+
// Flow-field rotation in flow-field mode, random otherwise
|
|
1242
|
+
const rotation = compositionMode === "flow-field" ? flowAngle(x, y) * 180 / Math.PI + (rng() - 0.5) * 30 : rng() * 360;
|
|
1243
|
+
// Positional color blending + jitter
|
|
1244
|
+
const fillBase = $1f63dc64b5593c73$var$getPositionalColor(x, y, width, height, colors, rng);
|
|
1245
|
+
const strokeBase = colors[Math.floor(rng() * colors.length)];
|
|
1246
|
+
const fillColor = (0, $b5a262d09b87e373$export$59539d800dbe6858)(fillBase, rng, 0.06);
|
|
1247
|
+
const strokeColor = (0, $b5a262d09b87e373$export$59539d800dbe6858)(strokeBase, rng, 0.05);
|
|
1248
|
+
// Semi-transparent fill
|
|
1249
|
+
const fillAlpha = 0.2 + rng() * 0.5;
|
|
1250
|
+
const transparentFill = (0, $b5a262d09b87e373$export$f2121afcad3d553f)(fillColor, fillAlpha);
|
|
1251
|
+
const strokeWidth = (0.5 + rng() * 2.0) * scaleFactor;
|
|
1252
|
+
ctx.globalAlpha = layerOpacity * (0.5 + rng() * 0.5);
|
|
1253
|
+
// Glow on sacred shapes more often
|
|
1254
|
+
const isSacred = $1f63dc64b5593c73$var$SACRED_SHAPES.includes(shape);
|
|
1255
|
+
const glowChance = isSacred ? 0.45 : 0.2;
|
|
1256
|
+
const hasGlow = rng() < glowChance;
|
|
1257
|
+
const glowRadius = hasGlow ? (8 + rng() * 20) * scaleFactor : 0;
|
|
1258
|
+
// Gradient fill on ~30%
|
|
1259
|
+
const hasGradient = rng() < 0.3;
|
|
1260
|
+
const gradientEnd = hasGradient ? (0, $b5a262d09b87e373$export$59539d800dbe6858)(colors[Math.floor(rng() * colors.length)], rng, 0.1) : undefined;
|
|
1261
|
+
(0, $e0f99502ff383dd8$export$bb35a6995ddbf32d)(ctx, shape, x, y, {
|
|
1262
|
+
fillColor: transparentFill,
|
|
1263
|
+
strokeColor: strokeColor,
|
|
1264
|
+
strokeWidth: strokeWidth,
|
|
1265
|
+
size: size,
|
|
1266
|
+
rotation: rotation,
|
|
1267
|
+
proportionType: "GOLDEN_RATIO",
|
|
1268
|
+
glowRadius: glowRadius,
|
|
1269
|
+
glowColor: hasGlow ? (0, $b5a262d09b87e373$export$f2121afcad3d553f)(fillColor, 0.6) : undefined,
|
|
1270
|
+
gradientFillEnd: gradientEnd
|
|
1271
|
+
});
|
|
1272
|
+
shapePositions.push({
|
|
1273
|
+
x: x,
|
|
1274
|
+
y: y,
|
|
1275
|
+
size: size
|
|
1276
|
+
});
|
|
1277
|
+
// ── 5b. Recursive nesting: ~15% of larger shapes get inner shapes ──
|
|
1278
|
+
if (size > adjustedMaxSize * 0.4 && rng() < 0.15) {
|
|
1279
|
+
const innerCount = 1 + Math.floor(rng() * 3);
|
|
1280
|
+
for(let n = 0; n < innerCount; n++){
|
|
1281
|
+
const innerShape = $1f63dc64b5593c73$var$pickShape(rng, Math.min(1, layerRatio + 0.3), shapeNames);
|
|
1282
|
+
const innerSize = size * (0.15 + rng() * 0.25);
|
|
1283
|
+
const innerOffX = (rng() - 0.5) * size * 0.4;
|
|
1284
|
+
const innerOffY = (rng() - 0.5) * size * 0.4;
|
|
1285
|
+
const innerRot = rng() * 360;
|
|
1286
|
+
const innerFill = (0, $b5a262d09b87e373$export$f2121afcad3d553f)((0, $b5a262d09b87e373$export$59539d800dbe6858)(colors[Math.floor(rng() * colors.length)], rng, 0.1), 0.3 + rng() * 0.4);
|
|
1287
|
+
ctx.globalAlpha = layerOpacity * 0.7;
|
|
1288
|
+
(0, $e0f99502ff383dd8$export$bb35a6995ddbf32d)(ctx, innerShape, x + innerOffX, y + innerOffY, {
|
|
1289
|
+
fillColor: innerFill,
|
|
1290
|
+
strokeColor: (0, $b5a262d09b87e373$export$f2121afcad3d553f)(strokeColor, 0.5),
|
|
1291
|
+
strokeWidth: strokeWidth * 0.6,
|
|
1292
|
+
size: innerSize,
|
|
1293
|
+
rotation: innerRot,
|
|
1294
|
+
proportionType: "GOLDEN_RATIO"
|
|
1295
|
+
});
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
// ── 6. Flow-line pass ──────────────────────────────────────────
|
|
1301
|
+
// Draw flowing curves that follow the hash-derived vector field
|
|
1302
|
+
const numFlowLines = 6 + Math.floor(rng() * 10);
|
|
1303
|
+
for(let i = 0; i < numFlowLines; i++){
|
|
1304
|
+
let fx = rng() * width;
|
|
1305
|
+
let fy = rng() * height;
|
|
1306
|
+
const steps = 30 + Math.floor(rng() * 40);
|
|
1307
|
+
const stepLen = (3 + rng() * 5) * scaleFactor;
|
|
1308
|
+
ctx.globalAlpha = 0.06 + rng() * 0.1;
|
|
1309
|
+
ctx.strokeStyle = (0, $b5a262d09b87e373$export$f2121afcad3d553f)(colors[Math.floor(rng() * colors.length)], 0.4);
|
|
1310
|
+
ctx.lineWidth = (0.5 + rng() * 1.5) * scaleFactor;
|
|
1311
|
+
ctx.beginPath();
|
|
1312
|
+
ctx.moveTo(fx, fy);
|
|
1313
|
+
for(let s = 0; s < steps; s++){
|
|
1314
|
+
const angle = flowAngle(fx, fy) + (rng() - 0.5) * 0.3;
|
|
1315
|
+
fx += Math.cos(angle) * stepLen;
|
|
1316
|
+
fy += Math.sin(angle) * stepLen;
|
|
1317
|
+
// Stay in bounds
|
|
1318
|
+
if (fx < 0 || fx > width || fy < 0 || fy > height) break;
|
|
1319
|
+
ctx.lineTo(fx, fy);
|
|
1320
|
+
}
|
|
1321
|
+
ctx.stroke();
|
|
1322
|
+
}
|
|
1323
|
+
// ── 7. Noise texture overlay ───────────────────────────────────
|
|
1324
|
+
// Subtle grain rendered as tiny semi-transparent dots
|
|
1325
|
+
const noiseRng = (0, $616009579e3d72c5$export$eaf9227667332084)((0, $616009579e3d72c5$export$e9cc707de01b7042)(gitHash, 777));
|
|
1326
|
+
const noiseDensity = Math.floor(width * height / 800);
|
|
1327
|
+
for(let i = 0; i < noiseDensity; i++){
|
|
1328
|
+
const nx = noiseRng() * width;
|
|
1329
|
+
const ny = noiseRng() * height;
|
|
1330
|
+
const brightness = noiseRng() > 0.5 ? 255 : 0;
|
|
1331
|
+
const alpha = 0.01 + noiseRng() * 0.03;
|
|
1332
|
+
ctx.globalAlpha = alpha;
|
|
1333
|
+
ctx.fillStyle = `rgba(${brightness},${brightness},${brightness},1)`;
|
|
1334
|
+
ctx.fillRect(nx, ny, 1 * scaleFactor, 1 * scaleFactor);
|
|
1335
|
+
}
|
|
1336
|
+
// ── 8. Organic connecting curves ───────────────────────────────
|
|
1337
|
+
if (shapePositions.length > 1) {
|
|
1338
|
+
const numCurves = Math.floor(8 * (width * height) / 1048576);
|
|
1339
|
+
ctx.lineWidth = 0.8 * scaleFactor;
|
|
1340
|
+
for(let i = 0; i < numCurves; i++){
|
|
1341
|
+
const idxA = Math.floor(rng() * shapePositions.length);
|
|
1342
|
+
const offset = 1 + Math.floor(rng() * Math.min(5, shapePositions.length - 1));
|
|
1343
|
+
const idxB = (idxA + offset) % shapePositions.length;
|
|
1344
|
+
const a = shapePositions[idxA];
|
|
1345
|
+
const b = shapePositions[idxB];
|
|
1346
|
+
const mx = (a.x + b.x) / 2;
|
|
1347
|
+
const my = (a.y + b.y) / 2;
|
|
1348
|
+
const dx = b.x - a.x;
|
|
1349
|
+
const dy = b.y - a.y;
|
|
1350
|
+
const dist = Math.hypot(dx, dy);
|
|
1351
|
+
const bulge = (rng() - 0.5) * dist * 0.4;
|
|
1352
|
+
const cpx = mx + -dy / (dist || 1) * bulge;
|
|
1353
|
+
const cpy = my + dx / (dist || 1) * bulge;
|
|
1354
|
+
ctx.globalAlpha = 0.06 + rng() * 0.1;
|
|
1355
|
+
ctx.strokeStyle = (0, $b5a262d09b87e373$export$f2121afcad3d553f)(colors[Math.floor(rng() * colors.length)], 0.3);
|
|
1356
|
+
ctx.beginPath();
|
|
1357
|
+
ctx.moveTo(a.x, a.y);
|
|
1358
|
+
ctx.quadraticCurveTo(cpx, cpy, b.x, b.y);
|
|
1359
|
+
ctx.stroke();
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
ctx.globalAlpha = 1;
|
|
1363
|
+
}
|
|
1364
|
+
|
|
1365
|
+
|
|
1366
|
+
|
|
1367
|
+
|
|
1368
|
+
/**
|
|
1369
|
+
* Render hash-derived art directly onto an HTMLCanvasElement.
|
|
1370
|
+
*
|
|
1371
|
+
* The canvas should already have the desired width/height set.
|
|
1372
|
+
* Config width/height will be inferred from the canvas if not provided.
|
|
1373
|
+
*
|
|
1374
|
+
* @param canvas - An HTMLCanvasElement (or OffscreenCanvas)
|
|
1375
|
+
* @param gitHash - Hex hash string used as the deterministic seed
|
|
1376
|
+
* @param config - Partial generation config (merged with defaults)
|
|
1377
|
+
*/ function $59c8fbfd7fd6ed6a$export$9379f53d1f28e74d(canvas, gitHash, config = {}) {
|
|
1378
|
+
const ctx = canvas.getContext("2d");
|
|
1379
|
+
if (!ctx) throw new Error("Failed to get 2D rendering context from canvas");
|
|
1380
|
+
const finalConfig = {
|
|
1381
|
+
width: canvas.width,
|
|
1382
|
+
height: canvas.height,
|
|
1383
|
+
...config
|
|
1384
|
+
};
|
|
1385
|
+
(0, $1f63dc64b5593c73$export$29a844702096332e)(ctx, gitHash, finalConfig);
|
|
1386
|
+
}
|
|
1387
|
+
/**
|
|
1388
|
+
* Render hash-derived art and return it as a Blob (browser-native).
|
|
1389
|
+
*
|
|
1390
|
+
* @param gitHash - Hex hash string used as the deterministic seed
|
|
1391
|
+
* @param config - Partial generation config (merged with defaults)
|
|
1392
|
+
* @returns A Promise that resolves to a PNG Blob
|
|
1393
|
+
*/ async function $59c8fbfd7fd6ed6a$export$ff855b1b91b18a57(gitHash, config = {}) {
|
|
1394
|
+
const finalConfig = {
|
|
1395
|
+
...(0, $81c1b644006d48ec$export$c2f8e0cc249a8d8f),
|
|
1396
|
+
...config
|
|
1397
|
+
};
|
|
1398
|
+
const { width: width, height: height } = finalConfig;
|
|
1399
|
+
const canvas = new OffscreenCanvas(width, height);
|
|
1400
|
+
const ctx = canvas.getContext("2d");
|
|
1401
|
+
if (!ctx) throw new Error("Failed to get 2D rendering context from OffscreenCanvas");
|
|
1402
|
+
(0, $1f63dc64b5593c73$export$29a844702096332e)(ctx, gitHash, finalConfig);
|
|
1403
|
+
return canvas.convertToBlob({
|
|
1404
|
+
type: "image/png"
|
|
1405
|
+
});
|
|
1406
|
+
}
|
|
1407
|
+
/**
|
|
1408
|
+
* Render hash-derived art and return it as a data URL string.
|
|
1409
|
+
*
|
|
1410
|
+
* @param gitHash - Hex hash string used as the deterministic seed
|
|
1411
|
+
* @param config - Partial generation config (merged with defaults)
|
|
1412
|
+
* @returns A data:image/png;base64,… string
|
|
1413
|
+
*/ function $59c8fbfd7fd6ed6a$export$ef85a3c26609a653(gitHash, config = {}) {
|
|
1414
|
+
const finalConfig = {
|
|
1415
|
+
...(0, $81c1b644006d48ec$export$c2f8e0cc249a8d8f),
|
|
1416
|
+
...config
|
|
1417
|
+
};
|
|
1418
|
+
const { width: width, height: height } = finalConfig;
|
|
1419
|
+
const canvas = document.createElement("canvas");
|
|
1420
|
+
canvas.width = width;
|
|
1421
|
+
canvas.height = height;
|
|
1422
|
+
const ctx = canvas.getContext("2d");
|
|
1423
|
+
if (!ctx) throw new Error("Failed to get 2D rendering context");
|
|
1424
|
+
(0, $1f63dc64b5593c73$export$29a844702096332e)(ctx, gitHash, finalConfig);
|
|
1425
|
+
return canvas.toDataURL("image/png");
|
|
1426
|
+
}
|
|
1427
|
+
|
|
1428
|
+
|
|
1429
|
+
export {$59c8fbfd7fd6ed6a$export$9379f53d1f28e74d as renderToCanvas, $59c8fbfd7fd6ed6a$export$ff855b1b91b18a57 as generateImageBlob, $59c8fbfd7fd6ed6a$export$ef85a3c26609a653 as generateDataURL, $1f63dc64b5593c73$export$29a844702096332e as renderHashArt, $e0ea14d2e2f06463$export$9265403940be6b4 as PRESETS, $81c1b644006d48ec$export$c2f8e0cc249a8d8f as DEFAULT_CONFIG};
|
|
1430
|
+
//# sourceMappingURL=browser.js.map
|