madansa7 commited on
Commit
a24c6e5
·
verified ·
1 Parent(s): ecc51a2

Add 3 files

Browse files
Files changed (3) hide show
  1. README.md +7 -5
  2. index.html +915 -19
  3. prompts.txt +1 -0
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Mandala New
3
- emoji: 🏃
4
- colorFrom: yellow
5
- colorTo: blue
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: mandala-new
3
+ emoji: 🐳
4
+ colorFrom: purple
5
+ colorTo: yellow
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,915 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Mandalas Creator - Interactive Radial Art Maker</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://cdn.jsdelivr.net/npm/fabric@5.3.1/dist/fabric.min.js"></script>
9
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
10
+ <style>
11
+ @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap');
12
+
13
+ :root {
14
+ --primary: #6366f1;
15
+ --dark: #0f172a;
16
+ --light: #f8fafc;
17
+ --gold: linear-gradient(135deg, #FFD700 0%, #D4AF37 100%);
18
+ --silver: linear-gradient(135deg, #C0C0C0 0%, #A8A8A8 100%);
19
+ --copper: linear-gradient(135deg, #B87333 0%, #9C5B2D 100%);
20
+ }
21
+
22
+ body {
23
+ font-family: 'Poppins', sans-serif;
24
+ background-color: var(--dark);
25
+ color: var(--light);
26
+ overflow: hidden;
27
+ touch-action: none;
28
+ }
29
+
30
+ .gradient-bg {
31
+ background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%);
32
+ }
33
+
34
+ .tool-btn {
35
+ @apply p-2 rounded-lg hover:bg-slate-700 transition-all duration-200;
36
+ }
37
+
38
+ .tool-btn.active {
39
+ @apply bg-indigo-600 text-white;
40
+ }
41
+
42
+ .color-swatch {
43
+ @apply w-8 h-8 rounded-full cursor-pointer border-2 border-transparent hover:border-white transition-all;
44
+ }
45
+
46
+ .metallic {
47
+ background-size: 200% 200%;
48
+ background-position: center;
49
+ }
50
+
51
+ .metallic.gold {
52
+ background-image: var(--gold);
53
+ }
54
+
55
+ .metallic.silver {
56
+ background-image: var(--silver);
57
+ }
58
+
59
+ .metallic.copper {
60
+ background-image: var(--copper);
61
+ }
62
+
63
+ canvas {
64
+ touch-action: none;
65
+ }
66
+
67
+ .slide-fade-enter-active {
68
+ transition: all 0.3s ease-out;
69
+ }
70
+
71
+ .slide-fade-leave-active {
72
+ transition: all 0.3s cubic-bezier(1, 0.5, 0.8, 1);
73
+ }
74
+
75
+ .slide-fade-enter-from,
76
+ .slide-fade-leave-to {
77
+ transform: translateX(20px);
78
+ opacity: 0;
79
+ }
80
+
81
+ .glow {
82
+ filter: drop-shadow(0 0 8px currentColor);
83
+ }
84
+
85
+ .neon-text {
86
+ text-shadow: 0 0 5px #fff, 0 0 10px #fff, 0 0 15px #fff, 0 0 20px #ff00de;
87
+ }
88
+
89
+ .custom-scrollbar::-webkit-scrollbar {
90
+ width: 6px;
91
+ height: 6px;
92
+ }
93
+
94
+ .custom-scrollbar::-webkit-scrollbar-track {
95
+ background: rgba(255,255,255,0.1);
96
+ border-radius: 10px;
97
+ }
98
+
99
+ .custom-scrollbar::-webkit-scrollbar-thumb {
100
+ background: rgba(255,255,255,0.3);
101
+ border-radius: 10px;
102
+ }
103
+
104
+ .custom-scrollbar::-webkit-scrollbar-thumb:hover {
105
+ background: rgba(255,255,255,0.5);
106
+ }
107
+ </style>
108
+ </head>
109
+ <body class="gradient-bg h-screen flex flex-col">
110
+ <!-- Header -->
111
+ <header class="bg-slate-900/50 backdrop-blur-md border-b border-slate-800 p-4 flex justify-between items-center">
112
+ <div class="flex items-center space-x-2">
113
+ <i class="fas fa-mandala text-2xl text-indigo-500"></i>
114
+ <h1 class="text-xl font-bold neon-text">Mandalas Creator</h1>
115
+ </div>
116
+ <div class="flex space-x-3">
117
+ <button id="exportBtn" class="bg-indigo-600 hover:bg-indigo-700 px-4 py-2 rounded-lg flex items-center space-x-2 transition-all">
118
+ <i class="fas fa-download"></i>
119
+ <span>Export</span>
120
+ </button>
121
+ <button id="clearBtn" class="bg-rose-600 hover:bg-rose-700 px-4 py-2 rounded-lg flex items-center space-x-2 transition-all">
122
+ <i class="fas fa-trash"></i>
123
+ <span>Clear</span>
124
+ </button>
125
+ </div>
126
+ </header>
127
+
128
+ <!-- Main Content -->
129
+ <div class="flex flex-1 overflow-hidden">
130
+ <!-- Left Toolbar -->
131
+ <div class="w-16 bg-slate-900/50 border-r border-slate-800 flex flex-col items-center py-4 space-y-6">
132
+ <div class="tool-group">
133
+ <div class="text-xs text-slate-400 mb-1">Tools</div>
134
+ <button id="brushTool" class="tool-btn active" title="Brush">
135
+ <i class="fas fa-paintbrush"></i>
136
+ </button>
137
+ <button id="shapeTool" class="tool-btn" title="Shapes">
138
+ <i class="fas fa-shapes"></i>
139
+ </button>
140
+ <button id="gradientTool" class="tool-btn" title="Gradient">
141
+ <i class="fas fa-fill-drip"></i>
142
+ </button>
143
+ <button id="eraseTool" class="tool-btn" title="Eraser">
144
+ <i class="fas fa-eraser"></i>
145
+ </button>
146
+ </div>
147
+
148
+ <div class="tool-group">
149
+ <div class="text-xs text-slate-400 mb-1">Symmetry</div>
150
+ <button id="symmetry6" class="tool-btn" title="6-fold">
151
+ <span>6</span>
152
+ </button>
153
+ <button id="symmetry8" class="tool-btn active" title="8-fold">
154
+ <span>8</span>
155
+ </button>
156
+ <button id="symmetry12" class="tool-btn" title="12-fold">
157
+ <span>12</span>
158
+ </button>
159
+ </div>
160
+
161
+ <div class="tool-group">
162
+ <div class="text-xs text-slate-400 mb-1">Effects</div>
163
+ <button id="glowEffect" class="tool-btn" title="Glow">
164
+ <i class="fas fa-lightbulb"></i>
165
+ </button>
166
+ <button id="shadowEffect" class="tool-btn" title="Shadow">
167
+ <i class="fas fa-cloud"></i>
168
+ </button>
169
+ <button id="embossEffect" class="tool-btn" title="Emboss">
170
+ <i class="fas fa-mountain"></i>
171
+ </button>
172
+ </div>
173
+ </div>
174
+
175
+ <!-- Canvas Area -->
176
+ <div class="flex-1 relative overflow-hidden">
177
+ <div id="canvas-container" class="absolute inset-0 flex items-center justify-center">
178
+ <canvas id="mandalaCanvas" width="800" height="800"></canvas>
179
+ </div>
180
+
181
+ <!-- Floating Controls -->
182
+ <div class="absolute bottom-4 left-1/2 transform -translate-x-1/2 bg-slate-900/80 backdrop-blur-md rounded-full px-4 py-2 flex items-center space-x-4 shadow-lg border border-slate-800">
183
+ <div class="flex items-center space-x-2">
184
+ <span class="text-sm text-slate-300">Size:</span>
185
+ <input id="brushSize" type="range" min="1" max="50" value="5" class="w-24">
186
+ <span id="brushSizeValue" class="text-sm w-8 text-center">5</span>
187
+ </div>
188
+ <div class="flex items-center space-x-2">
189
+ <span class="text-sm text-slate-300">Opacity:</span>
190
+ <input id="brushOpacity" type="range" min="10" max="100" value="100" class="w-24">
191
+ <span id="brushOpacityValue" class="text-sm w-8 text-center">100</span>
192
+ </div>
193
+ <div class="h-6 w-px bg-slate-700"></div>
194
+ <button id="undoBtn" class="text-slate-300 hover:text-white" title="Undo">
195
+ <i class="fas fa-undo"></i>
196
+ </button>
197
+ <button id="redoBtn" class="text-slate-300 hover:text-white" title="Redo">
198
+ <i class="fas fa-redo"></i>
199
+ </button>
200
+ <div class="h-6 w-px bg-slate-700"></div>
201
+ <button id="rotateBtn" class="text-slate-300 hover:text-white" title="Rotate Canvas">
202
+ <i class="fas fa-sync-alt"></i>
203
+ </button>
204
+ <button id="centerBtn" class="text-slate-300 hover:text-white" title="Center View">
205
+ <i class="fas fa-crosshairs"></i>
206
+ </button>
207
+ </div>
208
+ </div>
209
+
210
+ <!-- Right Panel -->
211
+ <div class="w-64 bg-slate-900/50 border-l border-slate-800 flex flex-col">
212
+ <div class="p-4 border-b border-slate-800">
213
+ <h3 class="font-medium text-slate-200 mb-2">Color Palette</h3>
214
+ <div class="grid grid-cols-5 gap-2">
215
+ <div class="color-swatch bg-red-500" data-color="#ef4444"></div>
216
+ <div class="color-swatch bg-orange-500" data-color="#f97316"></div>
217
+ <div class="color-swatch bg-yellow-500" data-color="#eab308"></div>
218
+ <div class="color-swatch bg-green-500" data-color="#22c55e"></div>
219
+ <div class="color-swatch bg-blue-500" data-color="#3b82f6"></div>
220
+ <div class="color-swatch bg-indigo-500" data-color="#6366f1"></div>
221
+ <div class="color-swatch bg-purple-500" data-color="#a855f7"></div>
222
+ <div class="color-swatch bg-pink-500" data-color="#ec4899"></div>
223
+ <div class="color-swatch bg-white" data-color="#ffffff"></div>
224
+ <div class="color-swatch bg-black" data-color="#000000"></div>
225
+ <div class="color-swatch metallic gold" data-color="gold"></div>
226
+ <div class="color-swatch metallic silver" data-color="silver"></div>
227
+ <div class="color-swatch metallic copper" data-color="copper"></div>
228
+ <div class="color-swatch bg-gradient-to-br from-purple-500 to-pink-500" data-color="purple-pink-gradient"></div>
229
+ <div class="color-swatch bg-gradient-to-br from-blue-500 to-teal-400" data-color="blue-teal-gradient"></div>
230
+ </div>
231
+
232
+ <div class="mt-4">
233
+ <label class="text-sm text-slate-300 block mb-1">Custom Color</label>
234
+ <input type="color" id="customColor" value="#3b82f6" class="w-full h-10 cursor-pointer">
235
+ </div>
236
+ </div>
237
+
238
+ <div class="p-4 border-b border-slate-800">
239
+ <h3 class="font-medium text-slate-200 mb-2">Shapes</h3>
240
+ <div class="grid grid-cols-3 gap-2">
241
+ <button class="shape-option p-2 rounded border border-slate-700 hover:bg-slate-800" data-shape="circle">
242
+ <i class="fas fa-circle text-lg"></i>
243
+ </button>
244
+ <button class="shape-option p-2 rounded border border-slate-700 hover:bg-slate-800" data-shape="teardrop">
245
+ <i class="fas fa-tint text-lg"></i>
246
+ </button>
247
+ <button class="shape-option p-2 rounded border border-slate-700 hover:bg-slate-800" data-shape="petal">
248
+ <i class="fas fa-leaf text-lg"></i>
249
+ </button>
250
+ <button class="shape-option p-2 rounded border border-slate-700 hover:bg-slate-800" data-shape="star">
251
+ <i class="fas fa-star text-lg"></i>
252
+ </button>
253
+ <button class="shape-option p-2 rounded border border-slate-700 hover:bg-slate-800" data-shape="ring">
254
+ <i class="fas fa-ring text-lg"></i>
255
+ </button>
256
+ <button class="shape-option p-2 rounded border border-slate-700 hover:bg-slate-800" data-shape="lotus">
257
+ <i class="fas fa-spa text-lg"></i>
258
+ </button>
259
+ </div>
260
+
261
+ <div class="mt-3">
262
+ <label class="text-sm text-slate-300 block mb-1">Shape Size</label>
263
+ <input type="range" id="shapeSize" min="10" max="100" value="30" class="w-full">
264
+ </div>
265
+ </div>
266
+
267
+ <div class="p-4 border-b border-slate-800">
268
+ <h3 class="font-medium text-slate-200 mb-2">Layers</h3>
269
+ <div id="layersList" class="space-y-2 max-h-40 overflow-y-auto custom-scrollbar">
270
+ <!-- Layers will be added here dynamically -->
271
+ </div>
272
+ <button id="addLayerBtn" class="mt-2 w-full bg-slate-800 hover:bg-slate-700 py-1 rounded text-sm">
273
+ <i class="fas fa-plus mr-1"></i> Add Layer
274
+ </button>
275
+ </div>
276
+
277
+ <div class="p-4">
278
+ <h3 class="font-medium text-slate-200 mb-2">Effects</h3>
279
+ <div class="space-y-3">
280
+ <div>
281
+ <label class="text-sm text-slate-300 block mb-1">Glow Intensity</label>
282
+ <input type="range" id="glowIntensity" min="0" max="20" value="0" class="w-full">
283
+ </div>
284
+ <div>
285
+ <label class="text-sm text-slate-300 block mb-1">Shadow Blur</label>
286
+ <input type="range" id="shadowBlur" min="0" max="20" value="0" class="w-full">
287
+ </div>
288
+ <div>
289
+ <label class="text-sm text-slate-300 block mb-1">Light Angle</label>
290
+ <input type="range" id="lightAngle" min="0" max="360" value="45" class="w-full">
291
+ </div>
292
+ </div>
293
+ </div>
294
+ </div>
295
+ </div>
296
+
297
+ <!-- Export Modal -->
298
+ <div id="exportModal" class="fixed inset-0 bg-black bg-opacity-70 flex items-center justify-center z-50 hidden">
299
+ <div class="bg-slate-800 rounded-lg p-6 w-full max-w-md">
300
+ <div class="flex justify-between items-center mb-4">
301
+ <h3 class="text-xl font-bold">Export Mandala</h3>
302
+ <button id="closeExportModal" class="text-slate-400 hover:text-white">
303
+ <i class="fas fa-times"></i>
304
+ </button>
305
+ </div>
306
+
307
+ <div class="space-y-4">
308
+ <div>
309
+ <label class="block text-sm font-medium text-slate-300 mb-1">Format</label>
310
+ <select id="exportFormat" class="w-full bg-slate-700 border border-slate-600 rounded px-3 py-2 text-white">
311
+ <option value="png">PNG (Transparent)</option>
312
+ <option value="png-black">PNG (Black Background)</option>
313
+ <option value="svg">SVG (Vector)</option>
314
+ </select>
315
+ </div>
316
+
317
+ <div>
318
+ <label class="block text-sm font-medium text-slate-300 mb-1">Resolution</label>
319
+ <select id="exportResolution" class="w-full bg-slate-700 border border-slate-600 rounded px-3 py-2 text-white">
320
+ <option value="1x">1x (800×800)</option>
321
+ <option value="2x">2x (1600×1600)</option>
322
+ <option value="4x">4x (3200×3200)</option>
323
+ </select>
324
+ </div>
325
+
326
+ <div class="pt-2">
327
+ <button id="confirmExport" class="w-full bg-indigo-600 hover:bg-indigo-700 py-2 rounded-lg">
328
+ Export Now
329
+ </button>
330
+ </div>
331
+ </div>
332
+ </div>
333
+ </div>
334
+
335
+ <script>
336
+ document.addEventListener('DOMContentLoaded', function() {
337
+ // Initialize Fabric.js canvas
338
+ const canvas = new fabric.Canvas('mandalaCanvas', {
339
+ isDrawingMode: true,
340
+ backgroundColor: 'transparent',
341
+ selection: false,
342
+ preserveObjectStacking: true
343
+ });
344
+
345
+ // Canvas setup
346
+ const canvasContainer = document.getElementById('canvas-container');
347
+ function resizeCanvas() {
348
+ const size = Math.min(window.innerWidth - 80, window.innerHeight - 120);
349
+ canvas.setWidth(size);
350
+ canvas.setHeight(size);
351
+ canvas.renderAll();
352
+ }
353
+ resizeCanvas();
354
+ window.addEventListener('resize', resizeCanvas);
355
+
356
+ // App state
357
+ const state = {
358
+ currentTool: 'brush',
359
+ currentColor: '#3b82f6',
360
+ brushSize: 5,
361
+ brushOpacity: 1,
362
+ symmetry: 8,
363
+ glowIntensity: 0,
364
+ shadowBlur: 0,
365
+ lightAngle: 45,
366
+ currentShape: 'circle',
367
+ shapeSize: 30,
368
+ layers: [],
369
+ currentLayer: null,
370
+ history: [],
371
+ historyIndex: -1
372
+ };
373
+
374
+ // Initialize first layer
375
+ addNewLayer();
376
+
377
+ // Tools selection
378
+ document.getElementById('brushTool').addEventListener('click', () => {
379
+ setTool('brush');
380
+ canvas.isDrawingMode = true;
381
+ });
382
+
383
+ document.getElementById('shapeTool').addEventListener('click', () => {
384
+ setTool('shape');
385
+ canvas.isDrawingMode = false;
386
+ });
387
+
388
+ document.getElementById('gradientTool').addEventListener('click', () => {
389
+ setTool('gradient');
390
+ canvas.isDrawingMode = false;
391
+ });
392
+
393
+ document.getElementById('eraseTool').addEventListener('click', () => {
394
+ setTool('erase');
395
+ canvas.isDrawingMode = true;
396
+ });
397
+
398
+ function setTool(tool) {
399
+ state.currentTool = tool;
400
+ document.querySelectorAll('.tool-btn').forEach(btn => btn.classList.remove('active'));
401
+
402
+ switch(tool) {
403
+ case 'brush':
404
+ document.getElementById('brushTool').classList.add('active');
405
+ canvas.freeDrawingBrush = new fabric.PencilBrush(canvas);
406
+ canvas.freeDrawingBrush.color = state.currentColor;
407
+ canvas.freeDrawingBrush.width = state.brushSize;
408
+ break;
409
+ case 'shape':
410
+ document.getElementById('shapeTool').classList.add('active');
411
+ break;
412
+ case 'gradient':
413
+ document.getElementById('gradientTool').classList.add('active');
414
+ break;
415
+ case 'erase':
416
+ document.getElementById('eraseTool').classList.add('active');
417
+ canvas.freeDrawingBrush = new fabric.PencilBrush(canvas);
418
+ canvas.freeDrawingBrush.color = 'rgba(0,0,0,0)';
419
+ canvas.freeDrawingBrush.width = state.brushSize;
420
+ break;
421
+ }
422
+ }
423
+
424
+ // Symmetry selection
425
+ document.getElementById('symmetry6').addEventListener('click', () => setSymmetry(6));
426
+ document.getElementById('symmetry8').addEventListener('click', () => setSymmetry(8));
427
+ document.getElementById('symmetry12').addEventListener('click', () => setSymmetry(12));
428
+
429
+ function setSymmetry(count) {
430
+ state.symmetry = count;
431
+ document.querySelectorAll('.tool-group:nth-child(2) .tool-btn').forEach(btn => btn.classList.remove('active'));
432
+ document.getElementById(`symmetry${count}`).classList.add('active');
433
+ }
434
+
435
+ // Brush settings
436
+ document.getElementById('brushSize').addEventListener('input', function() {
437
+ state.brushSize = parseInt(this.value);
438
+ document.getElementById('brushSizeValue').textContent = state.brushSize;
439
+ if (canvas.freeDrawingBrush) {
440
+ canvas.freeDrawingBrush.width = state.brushSize;
441
+ }
442
+ });
443
+
444
+ document.getElementById('brushOpacity').addEventListener('input', function() {
445
+ state.brushOpacity = parseInt(this.value) / 100;
446
+ document.getElementById('brushOpacityValue').textContent = parseInt(this.value);
447
+ if (canvas.freeDrawingBrush && state.currentTool !== 'erase') {
448
+ const color = fabric.util.colorValues(state.currentColor);
449
+ canvas.freeDrawingBrush.color = `rgba(${color[0]}, ${color[1]}, ${color[2]}, ${state.brushOpacity})`;
450
+ }
451
+ });
452
+
453
+ // Color selection
454
+ document.querySelectorAll('.color-swatch').forEach(swatch => {
455
+ swatch.addEventListener('click', function() {
456
+ const color = this.getAttribute('data-color');
457
+ if (color.includes('gradient')) {
458
+ // Handle gradient colors
459
+ state.currentColor = color;
460
+ } else {
461
+ // Solid and metallic colors
462
+ state.currentColor = color;
463
+ const colorEl = document.getElementById('customColor');
464
+ if (colorEl) colorEl.value = color;
465
+
466
+ if (canvas.freeDrawingBrush && state.currentTool !== 'erase') {
467
+ const colorValues = fabric.util.colorValues(color);
468
+ canvas.freeDrawingBrush.color = `rgba(${colorValues[0]}, ${colorValues[1]}, ${colorValues[2]}, ${state.brushOpacity})`;
469
+ }
470
+ }
471
+ });
472
+ });
473
+
474
+ document.getElementById('customColor').addEventListener('input', function() {
475
+ state.currentColor = this.value;
476
+ if (canvas.freeDrawingBrush && state.currentTool !== 'erase') {
477
+ const colorValues = fabric.util.colorValues(this.value);
478
+ canvas.freeDrawingBrush.color = `rgba(${colorValues[0]}, ${colorValues[1]}, ${colorValues[2]}, ${state.brushOpacity})`;
479
+ }
480
+ });
481
+
482
+ // Shape selection
483
+ document.querySelectorAll('.shape-option').forEach(option => {
484
+ option.addEventListener('click', function() {
485
+ state.currentShape = this.getAttribute('data-shape');
486
+ });
487
+ });
488
+
489
+ document.getElementById('shapeSize').addEventListener('input', function() {
490
+ state.shapeSize = parseInt(this.value);
491
+ });
492
+
493
+ // Effects
494
+ document.getElementById('glowIntensity').addEventListener('input', function() {
495
+ state.glowIntensity = parseInt(this.value);
496
+ });
497
+
498
+ document.getElementById('shadowBlur').addEventListener('input', function() {
499
+ state.shadowBlur = parseInt(this.value);
500
+ });
501
+
502
+ document.getElementById('lightAngle').addEventListener('input', function() {
503
+ state.lightAngle = parseInt(this.value);
504
+ });
505
+
506
+ // Canvas interaction
507
+ canvas.on('mouse:down', function(options) {
508
+ if (state.currentTool === 'shape') {
509
+ createSymmetricalShape(options.e.clientX, options.e.clientY);
510
+ }
511
+ });
512
+
513
+ canvas.on('touch:start', function(options) {
514
+ if (state.currentTool === 'shape') {
515
+ const touch = options.e.touches[0];
516
+ createSymmetricalShape(touch.clientX, touch.clientY);
517
+ }
518
+ });
519
+
520
+ function createSymmetricalShape(x, y) {
521
+ const pointer = canvas.getPointer(new fabric.Event(x, y));
522
+ const center = { x: canvas.width / 2, y: canvas.height / 2 };
523
+
524
+ for (let i = 0; i < state.symmetry; i++) {
525
+ const angle = (i * (360 / state.symmetry)) * (Math.PI / 180);
526
+ const distance = Math.sqrt(
527
+ Math.pow(pointer.x - center.x, 2) +
528
+ Math.pow(pointer.y - center.y, 2)
529
+ );
530
+
531
+ const newX = center.x + distance * Math.cos(angle);
532
+ const newY = center.y + distance * Math.sin(angle);
533
+
534
+ let shape;
535
+ switch (state.currentShape) {
536
+ case 'circle':
537
+ shape = new fabric.Circle({
538
+ left: newX - state.shapeSize / 2,
539
+ top: newY - state.shapeSize / 2,
540
+ radius: state.shapeSize / 2,
541
+ fill: state.currentColor,
542
+ originX: 'center',
543
+ originY: 'center'
544
+ });
545
+ break;
546
+ case 'teardrop':
547
+ // Teardrop shape using Path
548
+ const teardropPath = `M ${newX} ${newY - state.shapeSize/2}
549
+ Q ${newX + state.shapeSize/2} ${newY} ${newX} ${newY + state.shapeSize/2}
550
+ Q ${newX - state.shapeSize/2} ${newY} ${newX} ${newY - state.shapeSize/2} Z`;
551
+ shape = new fabric.Path(teardropPath, {
552
+ fill: state.currentColor,
553
+ originX: 'center',
554
+ originY: 'center'
555
+ });
556
+ break;
557
+ case 'petal':
558
+ // Petal shape using Path
559
+ const petalPath = `M ${newX} ${newY}
560
+ C ${newX + state.shapeSize/2} ${newY - state.shapeSize/3},
561
+ ${newX + state.shapeSize/3} ${newY - state.shapeSize},
562
+ ${newX} ${newY - state.shapeSize/1.5}
563
+ C ${newX - state.shapeSize/3} ${newY - state.shapeSize},
564
+ ${newX - state.shapeSize/2} ${newY - state.shapeSize/3},
565
+ ${newX} ${newY} Z`;
566
+ shape = new fabric.Path(petalPath, {
567
+ fill: state.currentColor,
568
+ originX: 'center',
569
+ originY: 'center'
570
+ });
571
+ break;
572
+ case 'star':
573
+ shape = new fabric.Polygon(createStarPoints(newX, newY, 5, state.shapeSize/2, state.shapeSize/4), {
574
+ fill: state.currentColor,
575
+ originX: 'center',
576
+ originY: 'center'
577
+ });
578
+ break;
579
+ case 'ring':
580
+ shape = new fabric.Circle({
581
+ left: newX,
582
+ top: newY,
583
+ radius: state.shapeSize / 2,
584
+ fill: 'transparent',
585
+ stroke: state.currentColor,
586
+ strokeWidth: 3,
587
+ originX: 'center',
588
+ originY: 'center'
589
+ });
590
+ break;
591
+ case 'lotus':
592
+ // Lotus shape with multiple petals
593
+ const lotusGroup = new fabric.Group([], {
594
+ left: newX,
595
+ top: newY,
596
+ originX: 'center',
597
+ originY: 'center'
598
+ });
599
+
600
+ // Center circle
601
+ lotusGroup.add(new fabric.Circle({
602
+ radius: state.shapeSize / 6,
603
+ fill: state.currentColor,
604
+ originX: 'center',
605
+ originY: 'center'
606
+ }));
607
+
608
+ // Petals
609
+ for (let j = 0; j < 8; j++) {
610
+ const petalAngle = j * (360 / 8) * (Math.PI / 180);
611
+ const petalPath = `M 0 0
612
+ C ${state.shapeSize/3} ${-state.shapeSize/4},
613
+ ${state.shapeSize/2} ${-state.shapeSize/6},
614
+ ${state.shapeSize/2} 0
615
+ C ${state.shapeSize/2} ${state.shapeSize/6},
616
+ ${state.shapeSize/3} ${state.shapeSize/4},
617
+ 0 0 Z`;
618
+ const petal = new fabric.Path(petalPath, {
619
+ fill: state.currentColor,
620
+ originX: 'center',
621
+ originY: 'center'
622
+ });
623
+ petal.rotate(j * 45);
624
+ lotusGroup.add(petal);
625
+ }
626
+
627
+ shape = lotusGroup;
628
+ break;
629
+ }
630
+
631
+ if (shape) {
632
+ applyEffects(shape);
633
+ canvas.add(shape);
634
+ saveToHistory();
635
+ }
636
+ }
637
+ }
638
+
639
+ function createStarPoints(centerX, centerY, points, outerRadius, innerRadius) {
640
+ const starPoints = [];
641
+ const angle = Math.PI / points;
642
+
643
+ for (let i = 0; i < 2 * points; i++) {
644
+ const radius = i % 2 === 0 ? outerRadius : innerRadius;
645
+ starPoints.push({
646
+ x: centerX + radius * Math.sin(i * angle),
647
+ y: centerY - radius * Math.cos(i * angle)
648
+ });
649
+ }
650
+
651
+ return starPoints;
652
+ }
653
+
654
+ function applyEffects(object) {
655
+ if (state.glowIntensity > 0) {
656
+ object.set({
657
+ shadow: new fabric.Shadow({
658
+ color: object.fill || object.stroke || '#ffffff',
659
+ blur: state.glowIntensity * 2,
660
+ offsetX: 0,
661
+ offsetY: 0
662
+ })
663
+ });
664
+ }
665
+
666
+ if (state.shadowBlur > 0) {
667
+ const angleRad = (state.lightAngle * Math.PI) / 180;
668
+ const distance = state.shadowBlur;
669
+ object.set({
670
+ shadow: new fabric.Shadow({
671
+ color: 'rgba(0,0,0,0.5)',
672
+ blur: state.shadowBlur * 2,
673
+ offsetX: Math.cos(angleRad) * distance,
674
+ offsetY: Math.sin(angleRad) * distance
675
+ })
676
+ });
677
+ }
678
+ }
679
+
680
+ // Layers management
681
+ function addNewLayer() {
682
+ const layerId = Date.now();
683
+ const layer = {
684
+ id: layerId,
685
+ name: `Layer ${state.layers.length + 1}`,
686
+ visible: true,
687
+ locked: false
688
+ };
689
+
690
+ state.layers.push(layer);
691
+ state.currentLayer = layerId;
692
+ updateLayersUI();
693
+ saveToHistory();
694
+ }
695
+
696
+ document.getElementById('addLayerBtn').addEventListener('click', addNewLayer);
697
+
698
+ function updateLayersUI() {
699
+ const layersList = document.getElementById('layersList');
700
+ layersList.innerHTML = '';
701
+
702
+ state.layers.forEach((layer, index) => {
703
+ const layerItem = document.createElement('div');
704
+ layerItem.className = `flex items-center justify-between p-2 rounded ${state.currentLayer === layer.id ? 'bg-slate-700' : 'bg-slate-800'}`;
705
+ layerItem.innerHTML = `
706
+ <div class="flex items-center space-x-2">
707
+ <button class="toggle-visibility" data-id="${layer.id}">
708
+ <i class="fas fa-eye${layer.visible ? '' : '-slash'}"></i>
709
+ </button>
710
+ <span class="text-sm">${layer.name}</span>
711
+ </div>
712
+ <div class="flex space-x-1">
713
+ <button class="lock-layer" data-id="${layer.id}">
714
+ <i class="fas fa-${layer.locked ? 'lock' : 'lock-open'}"></i>
715
+ </button>
716
+ <button class="delete-layer" data-id="${layer.id}">
717
+ <i class="fas fa-trash"></i>
718
+ </button>
719
+ </div>
720
+ `;
721
+
722
+ layerItem.addEventListener('click', () => {
723
+ state.currentLayer = layer.id;
724
+ updateLayersUI();
725
+ });
726
+
727
+ layersList.appendChild(layerItem);
728
+ });
729
+
730
+ // Add event listeners for the buttons
731
+ document.querySelectorAll('.toggle-visibility').forEach(btn => {
732
+ btn.addEventListener('click', function(e) {
733
+ e.stopPropagation();
734
+ const layerId = parseInt(this.getAttribute('data-id'));
735
+ const layer = state.layers.find(l => l.id === layerId);
736
+ if (layer) {
737
+ layer.visible = !layer.visible;
738
+ updateLayersUI();
739
+ saveToHistory();
740
+ }
741
+ });
742
+ });
743
+
744
+ document.querySelectorAll('.lock-layer').forEach(btn => {
745
+ btn.addEventListener('click', function(e) {
746
+ e.stopPropagation();
747
+ const layerId = parseInt(this.getAttribute('data-id'));
748
+ const layer = state.layers.find(l => l.id === layerId);
749
+ if (layer) {
750
+ layer.locked = !layer.locked;
751
+ updateLayersUI();
752
+ saveToHistory();
753
+ }
754
+ });
755
+ });
756
+
757
+ document.querySelectorAll('.delete-layer').forEach(btn => {
758
+ btn.addEventListener('click', function(e) {
759
+ e.stopPropagation();
760
+ const layerId = parseInt(this.getAttribute('data-id'));
761
+ if (state.layers.length > 1) {
762
+ state.layers = state.layers.filter(l => l.id !== layerId);
763
+ if (state.currentLayer === layerId) {
764
+ state.currentLayer = state.layers[0].id;
765
+ }
766
+ updateLayersUI();
767
+ saveToHistory();
768
+ } else {
769
+ alert("You can't delete the last layer.");
770
+ }
771
+ });
772
+ });
773
+ }
774
+
775
+ // History management
776
+ function saveToHistory() {
777
+ // Trim history if we've undone some actions
778
+ if (state.historyIndex < state.history.length - 1) {
779
+ state.history = state.history.slice(0, state.historyIndex + 1);
780
+ }
781
+
782
+ const canvasState = JSON.stringify(canvas.toJSON());
783
+ state.history.push(canvasState);
784
+ state.historyIndex = state.history.length - 1;
785
+ }
786
+
787
+ document.getElementById('undoBtn').addEventListener('click', function() {
788
+ if (state.historyIndex > 0) {
789
+ state.historyIndex--;
790
+ loadFromHistory();
791
+ }
792
+ });
793
+
794
+ document.getElementById('redoBtn').addEventListener('click', function() {
795
+ if (state.historyIndex < state.history.length - 1) {
796
+ state.historyIndex++;
797
+ loadFromHistory();
798
+ }
799
+ });
800
+
801
+ function loadFromHistory() {
802
+ if (state.historyIndex >= 0 && state.historyIndex < state.history.length) {
803
+ canvas.loadFromJSON(state.history[state.historyIndex], function() {
804
+ canvas.renderAll();
805
+ });
806
+ }
807
+ }
808
+
809
+ // Canvas events that should trigger history saves
810
+ canvas.on('path:created', saveToHistory);
811
+ canvas.on('object:added', saveToHistory);
812
+ canvas.on('object:modified', saveToHistory);
813
+ canvas.on('object:removed', saveToHistory);
814
+
815
+ // Export functionality
816
+ document.getElementById('exportBtn').addEventListener('click', function() {
817
+ document.getElementById('exportModal').classList.remove('hidden');
818
+ });
819
+
820
+ document.getElementById('closeExportModal').addEventListener('click', function() {
821
+ document.getElementById('exportModal').classList.add('hidden');
822
+ });
823
+
824
+ document.getElementById('confirmExport').addEventListener('click', function() {
825
+ const format = document.getElementById('exportFormat').value;
826
+ const resolution = document.getElementById('exportResolution').value;
827
+ let scale = 1;
828
+
829
+ switch (resolution) {
830
+ case '2x': scale = 2; break;
831
+ case '4x': scale = 4; break;
832
+ }
833
+
834
+ if (format === 'svg') {
835
+ // Export as SVG
836
+ const svg = canvas.toSVG();
837
+ const blob = new Blob([svg], {type: 'image/svg+xml'});
838
+ const url = URL.createObjectURL(blob);
839
+
840
+ const a = document.createElement('a');
841
+ a.href = url;
842
+ a.download = 'mandala-art.svg';
843
+ document.body.appendChild(a);
844
+ a.click();
845
+ document.body.removeChild(a);
846
+ URL.revokeObjectURL(url);
847
+ } else {
848
+ // Export as PNG
849
+ const bgColor = format === 'png-black' ? '#000000' : 'rgba(0,0,0,0)';
850
+
851
+ // Create a temporary canvas for export
852
+ const exportCanvas = document.createElement('canvas');
853
+ exportCanvas.width = canvas.width * scale;
854
+ exportCanvas.height = canvas.height * scale;
855
+ const exportContext = exportCanvas.getContext('2d');
856
+
857
+ // Fill background if needed
858
+ if (bgColor !== 'rgba(0,0,0,0)') {
859
+ exportContext.fillStyle = bgColor;
860
+ exportContext.fillRect(0, 0, exportCanvas.width, exportCanvas.height);
861
+ }
862
+
863
+ // Draw the canvas content scaled up
864
+ const dataUrl = canvas.toDataURL({
865
+ format: 'png',
866
+ multiplier: scale
867
+ });
868
+
869
+ const img = new Image();
870
+ img.onload = function() {
871
+ exportContext.drawImage(img, 0, 0);
872
+
873
+ // Create download link
874
+ const a = document.createElement('a');
875
+ a.href = exportCanvas.toDataURL('image/png');
876
+ a.download = 'mandala-art.png';
877
+ document.body.appendChild(a);
878
+ a.click();
879
+ document.body.removeChild(a);
880
+ };
881
+ img.src = dataUrl;
882
+ }
883
+
884
+ document.getElementById('exportModal').classList.add('hidden');
885
+ });
886
+
887
+ // Clear canvas
888
+ document.getElementById('clearBtn').addEventListener('click', function() {
889
+ if (confirm('Are you sure you want to clear the canvas?')) {
890
+ canvas.clear();
891
+ saveToHistory();
892
+ }
893
+ });
894
+
895
+ // Canvas navigation
896
+ document.getElementById('rotateBtn').addEventListener('click', function() {
897
+ // Rotate the canvas view
898
+ const angle = (canvas.angle || 0) + 15;
899
+ canvas.angle = angle % 360;
900
+ canvas.renderAll();
901
+ });
902
+
903
+ document.getElementById('centerBtn').addEventListener('click', function() {
904
+ // Center the canvas view
905
+ canvas.angle = 0;
906
+ canvas.renderAll();
907
+ });
908
+
909
+ // Initialize brush
910
+ setTool('brush');
911
+ setSymmetry(8);
912
+ });
913
+ </script>
914
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=madansa7/mandala-new" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
915
+ </html>
prompts.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ Design and develop a web-based interactive mandala art maker that allows users to draw complex, radially symmetrical mandalas using either touch (on mobile/tablet) or mouse input (desktop). The application should support multi-layered radial symmetry, enabling users to create intricate, 3D-looking mandala artworks. Incorporate a central geometry engine that mirrors strokes in real time across 6, 8, or 12 symmetrical axes, with controls to toggle the number of axes. Include a rich shape palette featuring teardrop petals, lotus shapes, circular droplets, stars, and layered rings. Users should be able to select from pre-set shape stamps or free-draw strokes, all adhering to the radial grid. Enable dynamic color gradients, including metallic shades like gold, silver, and blue, with controls for light source direction to simulate a 3D embossed effect. Integrate neon glow effects and inner/outer shadows to produce depth. Provide a customizable gradient editor and a palette of rich metallics, jewel tones, and soft matte colors. Allow layering and depth control (z-index) for each shape or stroke. Include smart snapping, alignment tools, and undo/redo functionality. Export options should include PNG (transparent or black background), SVG for vector editing, and optionally a time-lapse video of the creation process. Optimize the UI for creativity: minimalist dark mode interface, floating toolbars, and a rotating canvas view for convenience. Bonus features: procedural generation of symmetrical mandalas based on mood/color themes, AI-assisted design suggestion engine, and integration with platforms like Canva or Procreate for exporting layers.