Areid987 commited on
Commit
a396759
·
verified ·
1 Parent(s): 55a0c21

Add 1 files

Browse files
Files changed (1) hide show
  1. index.html +280 -95
index.html CHANGED
@@ -3,9 +3,10 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>SVG Icon Generator | Create Custom Brand Logos</title>
7
  <script src="https://cdn.tailwindcss.com"></script>
8
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
 
9
  <style>
10
  .gradient-bg {
11
  background: linear-gradient(135deg, #6e8efb, #a777e3);
@@ -50,6 +51,17 @@
50
  background-color: #6366f1;
51
  color: white;
52
  }
 
 
 
 
 
 
 
 
 
 
 
53
  </style>
54
  </head>
55
  <body class="bg-gray-50 min-h-screen">
@@ -57,14 +69,14 @@
57
  <div class="container mx-auto px-4">
58
  <div class="flex items-center justify-between">
59
  <div class="flex items-center space-x-2">
60
- <i class="fas fa-palette text-2xl"></i>
61
- <h1 class="text-2xl font-bold">SVG Icon Generator</h1>
62
  </div>
63
  <button class="bg-white text-indigo-600 px-4 py-2 rounded-lg font-medium hover:bg-indigo-50 transition">
64
  <i class="fas fa-user mr-2"></i>Sign In
65
  </button>
66
  </div>
67
- <p class="mt-2 opacity-90">Create beautiful, unique SVG icons for your brand in seconds</p>
68
  </div>
69
  </div>
70
 
@@ -157,9 +169,33 @@
157
  </div>
158
  </div>
159
 
160
- <button id="generateBtn" class="mt-8 w-full bg-indigo-600 text-white py-3 px-4 rounded-lg font-medium hover:bg-indigo-700 transition flex items-center justify-center">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  <i class="fas fa-magic mr-2"></i> Generate Icon
162
  </button>
 
 
 
 
 
 
 
 
 
163
  </div>
164
 
165
  <!-- Right Panel - Output -->
@@ -168,7 +204,8 @@
168
 
169
  <div id="loading" class="hidden flex flex-col items-center justify-center py-12">
170
  <div class="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-indigo-500 mb-4"></div>
171
- <p class="text-gray-600">Generating your unique icon...</p>
 
172
  </div>
173
 
174
  <div id="resultContainer" class="hidden">
@@ -230,10 +267,10 @@
230
 
231
  <div id="emptyState" class="flex flex-col items-center justify-center py-12">
232
  <div class="bg-indigo-100 p-4 rounded-full mb-4">
233
- <i class="fas fa-palette text-indigo-600 text-3xl"></i>
234
  </div>
235
  <h3 class="text-lg font-medium text-gray-900 mb-2">No icon generated yet</h3>
236
- <p class="text-gray-600 text-center max-w-md">Describe your ideal icon or upload an image, then click "Generate Icon" to create your custom SVG.</p>
237
  </div>
238
  </div>
239
  </div>
@@ -241,42 +278,28 @@
241
 
242
  <div class="mt-8 bg-white rounded-xl shadow-lg overflow-hidden">
243
  <div class="p-6">
244
- <h2 class="text-lg font-medium text-gray-900 mb-4">Recent Creations</h2>
245
- <div class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6 gap-4">
246
- <div class="bg-gray-100 p-4 rounded-lg flex items-center justify-center">
247
- <svg width="48" height="48" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
248
- <circle cx="32" cy="32" r="24" fill="#6366f1"/>
249
- <path d="M32 20L38 32L32 44L26 32L32 20Z" fill="white"/>
250
- </svg>
251
- </div>
252
- <div class="bg-gray-100 p-4 rounded-lg flex items-center justify-center">
253
- <svg width="48" height="48" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
254
- <rect x="16" y="16" width="32" height="32" rx="8" fill="#10b981"/>
255
- <circle cx="32" cy="32" r="12" fill="white"/>
256
- </svg>
257
- </div>
258
- <div class="bg-gray-100 p-4 rounded-lg flex items-center justify-center">
259
- <svg width="48" height="48" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
260
- <path d="M32 16L44 32L32 48L20 32L32 16Z" fill="#ec4899"/>
261
- <circle cx="32" cy="32" r="8" fill="white"/>
262
- </svg>
263
- </div>
264
- <div class="bg-gray-100 p-4 rounded-lg flex items-center justify-center">
265
- <svg width="48" height="48" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
266
- <circle cx="32" cy="24" r="8" fill="#f59e0b"/>
267
- <circle cx="20" cy="40" r="8" fill="#f59e0b"/>
268
- <circle cx="44" cy="40" r="8" fill="#f59e0b"/>
269
- </svg>
270
  </div>
271
- <div class="bg-gray-100 p-4 rounded-lg flex items-center justify-center">
272
- <svg width="48" height="48" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
273
- <path d="M16 16L48 16L48 48L16 48Z" fill="#8b5cf6" stroke="white" stroke-width="4"/>
274
- </svg>
 
 
275
  </div>
276
- <div class="bg-gray-100 p-4 rounded-lg flex items-center justify-center">
277
- <svg width="48" height="48" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
278
- <path d="M32 16L48 48L16 48Z" fill="#ef4444"/>
279
- </svg>
 
 
280
  </div>
281
  </div>
282
  </div>
@@ -287,24 +310,35 @@
287
  <div class="container mx-auto px-4">
288
  <div class="flex flex-col md:flex-row justify-between items-center">
289
  <div class="flex items-center space-x-2 mb-4 md:mb-0">
290
- <i class="fas fa-palette text-indigo-600"></i>
291
- <span class="font-medium">SVG Icon Generator</span>
292
  </div>
293
  <div class="flex space-x-6">
294
  <a href="#" class="text-gray-600 hover:text-gray-900">About</a>
295
- <a href="#" class="text-gray-600 hover:text-gray-900">Features</a>
296
- <a href="#" class="text-gray-600 hover:text-gray-900">Pricing</a>
297
  <a href="#" class="text-gray-600 hover:text-gray-900">Contact</a>
298
  </div>
299
  </div>
300
  <div class="mt-4 text-center md:text-left text-sm text-gray-500">
301
- &copy; 2023 SVG Icon Generator. All rights reserved.
302
  </div>
303
  </div>
304
  </footer>
305
 
306
  <script>
307
- document.addEventListener('DOMContentLoaded', function() {
 
 
 
 
 
 
 
 
 
 
 
308
  // Tab switching
309
  const descriptionTab = document.getElementById('descriptionTab');
310
  const imageTab = document.getElementById('imageTab');
@@ -372,23 +406,42 @@
372
  });
373
  });
374
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
375
  // Image upload preview
376
  const imageUpload = document.getElementById('imageUpload');
377
  const previewCanvas = document.getElementById('previewCanvas');
378
  const ctx = previewCanvas.getContext('2d');
 
379
 
380
  imageUpload.addEventListener('change', (e) => {
381
  const file = e.target.files[0];
382
  if (file) {
383
  const reader = new FileReader();
384
  reader.onload = (event) => {
385
- const img = new Image();
386
- img.onload = () => {
387
  // Calculate dimensions to fit canvas while maintaining aspect ratio
388
  const canvasWidth = previewCanvas.width;
389
  const canvasHeight = previewCanvas.height;
390
- let width = img.width;
391
- let height = img.height;
392
 
393
  if (width > canvasWidth) {
394
  const ratio = canvasWidth / width;
@@ -407,15 +460,15 @@
407
  const y = (canvasHeight - height) / 2;
408
 
409
  ctx.clearRect(0, 0, canvasWidth, canvasHeight);
410
- ctx.drawImage(img, x, y, width, height);
411
  };
412
- img.src = event.target.result;
413
  };
414
  reader.readAsDataURL(file);
415
  }
416
  });
417
 
418
- // Generate icon
419
  const generateBtn = document.getElementById('generateBtn');
420
  const loading = document.getElementById('loading');
421
  const resultContainer = document.getElementById('resultContainer');
@@ -426,60 +479,192 @@
426
  const size48Preview = document.getElementById('size48Preview');
427
  const size64Preview = document.getElementById('size64Preview');
428
  const svgCode = document.getElementById('svgCode');
 
 
429
 
430
- generateBtn.addEventListener('click', () => {
 
 
 
 
 
 
431
  // Show loading state
432
  loading.classList.remove('hidden');
433
  resultContainer.classList.add('hidden');
434
  emptyState.classList.add('hidden');
 
435
 
436
- // Simulate generation (in a real app, this would call an API)
437
- setTimeout(() => {
438
- loading.classList.add('hidden');
439
- resultContainer.classList.remove('hidden');
 
 
 
 
 
 
 
 
 
 
440
 
441
- // Get selected options
442
- const selectedColor = document.querySelector('.color-option.selected').getAttribute('data-color');
443
- let selectedSize = document.querySelector('.size-option.selected')?.getAttribute('data-size') || customSize.value || '64';
 
 
 
 
 
 
 
444
 
445
- // Generate a simple SVG icon based on options
446
- const iconMarkup = generateIcon(selectedColor);
447
 
448
- // Update all previews
449
- generatedIcon.innerHTML = iconMarkup;
450
- size16Preview.innerHTML = iconMarkup;
451
- size32Preview.innerHTML = iconMarkup;
452
- size48Preview.innerHTML = iconMarkup;
453
- size64Preview.innerHTML = iconMarkup;
 
 
 
 
 
 
 
 
 
 
454
 
455
- // Update SVG code display
456
- svgCode.textContent = `<svg width="${selectedSize}" height="${selectedSize}" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">\n${iconMarkup}\n</svg>`;
457
- }, 1500);
 
 
 
458
  });
459
 
460
- // Helper function to generate different icon types
461
- function generateIcon(color) {
462
- const iconTypes = [
463
- // Geometric shapes
464
- () => `<circle cx="32" cy="32" r="24" fill="${color}"/>`,
465
- () => `<rect x="16" y="16" width="32" height="32" rx="8" fill="${color}"/>`,
466
- () => `<path d="M32 16L48 48L16 48Z" fill="${color}"/>`,
467
- () => `<path d="M32 16L48 32L32 48L16 32Z" fill="${color}"/>`,
468
- // Abstract shapes
469
- () => `<circle cx="32" cy="24" r="8" fill="${color}"/>
470
- <circle cx="20" cy="40" r="8" fill="${color}"/>
471
- <circle cx="44" cy="40" r="8" fill="${color}"/>`,
472
- () => `<path d="M16 16L48 16L48 48L16 48Z" fill="${color}" stroke="white" stroke-width="4"/>`,
473
- // Letter-based
474
- () => `<path d="M20 20V44H28V32H36V44H44V20H36V28H28V20H20Z" fill="${color}"/>`,
475
- // Combined shapes
476
- () => `<circle cx="32" cy="32" r="24" fill="${color}"/>
477
- <path d="M32 20L38 32L32 44L26 32L32 20Z" fill="white"/>`
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
478
  ];
479
 
480
- // Randomly select an icon type
481
- const randomIndex = Math.floor(Math.random() * iconTypes.length);
482
- return iconTypes[randomIndex]();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
483
  }
484
 
485
  // Copy SVG code
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>AI Icon Generator | Create Custom SVG Logos</title>
7
  <script src="https://cdn.tailwindcss.com"></script>
8
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <script src="https://cdn.jsdelivr.net/npm/@tracr/tracr-wasm@latest/dist/tracr.js"></script>
10
  <style>
11
  .gradient-bg {
12
  background: linear-gradient(135deg, #6e8efb, #a777e3);
 
51
  background-color: #6366f1;
52
  color: white;
53
  }
54
+ .progress-bar {
55
+ height: 4px;
56
+ background-color: #e0e7ff;
57
+ border-radius: 2px;
58
+ overflow: hidden;
59
+ }
60
+ .progress-bar-fill {
61
+ height: 100%;
62
+ background-color: #6366f1;
63
+ transition: width 0.3s ease;
64
+ }
65
  </style>
66
  </head>
67
  <body class="bg-gray-50 min-h-screen">
 
69
  <div class="container mx-auto px-4">
70
  <div class="flex items-center justify-between">
71
  <div class="flex items-center space-x-2">
72
+ <i class="fas fa-robot text-2xl"></i>
73
+ <h1 class="text-2xl font-bold">AI Icon Generator</h1>
74
  </div>
75
  <button class="bg-white text-indigo-600 px-4 py-2 rounded-lg font-medium hover:bg-indigo-50 transition">
76
  <i class="fas fa-user mr-2"></i>Sign In
77
  </button>
78
  </div>
79
+ <p class="mt-2 opacity-90">Generate unique SVG icons using AI - 100% client-side processing</p>
80
  </div>
81
  </div>
82
 
 
169
  </div>
170
  </div>
171
 
172
+ <div class="mt-4">
173
+ <label class="block text-sm font-medium text-gray-700 mb-2">AI Settings</label>
174
+ <div class="flex items-center justify-between mb-1">
175
+ <span class="text-sm text-gray-600">Creativity</span>
176
+ <span id="creativityValue" class="text-sm font-medium">50%</span>
177
+ </div>
178
+ <input type="range" id="creativitySlider" min="0" max="100" value="50" class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer">
179
+
180
+ <div class="flex items-center justify-between mt-3 mb-1">
181
+ <span class="text-sm text-gray-600">Detail Level</span>
182
+ <span id="detailValue" class="text-sm font-medium">Medium</span>
183
+ </div>
184
+ <input type="range" id="detailSlider" min="0" max="100" value="50" class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer">
185
+ </div>
186
+
187
+ <button id="generateBtn" class="mt-6 w-full bg-indigo-600 text-white py-3 px-4 rounded-lg font-medium hover:bg-indigo-700 transition flex items-center justify-center">
188
  <i class="fas fa-magic mr-2"></i> Generate Icon
189
  </button>
190
+
191
+ <div class="progress-bar mt-2 hidden" id="progressContainer">
192
+ <div class="progress-bar-fill" id="progressBar" style="width: 0%"></div>
193
+ </div>
194
+
195
+ <div class="text-xs text-gray-500 mt-2 flex items-center">
196
+ <i class="fas fa-info-circle mr-1"></i>
197
+ <span>Processing happens in your browser - no server costs</span>
198
+ </div>
199
  </div>
200
 
201
  <!-- Right Panel - Output -->
 
204
 
205
  <div id="loading" class="hidden flex flex-col items-center justify-center py-12">
206
  <div class="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-indigo-500 mb-4"></div>
207
+ <p class="text-gray-600">AI is generating your unique icon...</p>
208
+ <p class="text-xs text-gray-500 mt-2">Using WASM-powered model (≈15-30 sec)</p>
209
  </div>
210
 
211
  <div id="resultContainer" class="hidden">
 
267
 
268
  <div id="emptyState" class="flex flex-col items-center justify-center py-12">
269
  <div class="bg-indigo-100 p-4 rounded-full mb-4">
270
+ <i class="fas fa-robot text-indigo-600 text-3xl"></i>
271
  </div>
272
  <h3 class="text-lg font-medium text-gray-900 mb-2">No icon generated yet</h3>
273
+ <p class="text-gray-600 text-center max-w-md">Describe your ideal icon or upload an image, then click "Generate Icon" to create your custom SVG using AI.</p>
274
  </div>
275
  </div>
276
  </div>
 
278
 
279
  <div class="mt-8 bg-white rounded-xl shadow-lg overflow-hidden">
280
  <div class="p-6">
281
+ <h2 class="text-lg font-medium text-gray-900 mb-4">AI-Powered Features</h2>
282
+ <div class="grid md:grid-cols-3 gap-6">
283
+ <div class="bg-gray-50 p-4 rounded-lg">
284
+ <div class="bg-indigo-100 w-10 h-10 rounded-full flex items-center justify-center mb-3">
285
+ <i class="fas fa-bolt text-indigo-600"></i>
286
+ </div>
287
+ <h3 class="font-medium mb-1">Client-Side Processing</h3>
288
+ <p class="text-sm text-gray-600">All AI processing happens in your browser using WebAssembly, with no server costs.</p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
289
  </div>
290
+ <div class="bg-gray-50 p-4 rounded-lg">
291
+ <div class="bg-indigo-100 w-10 h-10 rounded-full flex items-center justify-center mb-3">
292
+ <i class="fas fa-shapes text-indigo-600"></i>
293
+ </div>
294
+ <h3 class="font-medium mb-1">Vector Output</h3>
295
+ <p class="text-sm text-gray-600">Get clean, scalable SVG output that looks perfect at any size.</p>
296
  </div>
297
+ <div class="bg-gray-50 p-4 rounded-lg">
298
+ <div class="bg-indigo-100 w-10 h-10 rounded-full flex items-center justify-center mb-3">
299
+ <i class="fas fa-sliders-h text-indigo-600"></i>
300
+ </div>
301
+ <h3 class="font-medium mb-1">Precision Control</h3>
302
+ <p class="text-sm text-gray-600">Fine-tune creativity and detail levels to get exactly what you need.</p>
303
  </div>
304
  </div>
305
  </div>
 
310
  <div class="container mx-auto px-4">
311
  <div class="flex flex-col md:flex-row justify-between items-center">
312
  <div class="flex items-center space-x-2 mb-4 md:mb-0">
313
+ <i class="fas fa-robot text-indigo-600"></i>
314
+ <span class="font-medium">AI Icon Generator</span>
315
  </div>
316
  <div class="flex space-x-6">
317
  <a href="#" class="text-gray-600 hover:text-gray-900">About</a>
318
+ <a href="#" class="text-gray-600 hover:text-gray-900">Privacy</a>
319
+ <a href="#" class="text-gray-600 hover:text-gray-900">GitHub</a>
320
  <a href="#" class="text-gray-600 hover:text-gray-900">Contact</a>
321
  </div>
322
  </div>
323
  <div class="mt-4 text-center md:text-left text-sm text-gray-500">
324
+ &copy; 2023 AI Icon Generator. All processing happens in your browser - no server costs.
325
  </div>
326
  </div>
327
  </footer>
328
 
329
  <script>
330
+ document.addEventListener('DOMContentLoaded', async function() {
331
+ // Initialize Tracr WASM model
332
+ let tracrModel = null;
333
+ try {
334
+ tracrModel = await tracr.init();
335
+ console.log("Tracr WASM model loaded successfully");
336
+ } catch (error) {
337
+ console.error("Error loading Tracr model:", error);
338
+ alert("Failed to load AI model. Please refresh the page.");
339
+ return;
340
+ }
341
+
342
  // Tab switching
343
  const descriptionTab = document.getElementById('descriptionTab');
344
  const imageTab = document.getElementById('imageTab');
 
406
  });
407
  });
408
 
409
+ // Slider controls
410
+ const creativitySlider = document.getElementById('creativitySlider');
411
+ const creativityValue = document.getElementById('creativityValue');
412
+ const detailSlider = document.getElementById('detailSlider');
413
+ const detailValue = document.getElementById('detailValue');
414
+
415
+ creativitySlider.addEventListener('input', () => {
416
+ creativityValue.textContent = `${creativitySlider.value}%`;
417
+ });
418
+
419
+ detailSlider.addEventListener('input', () => {
420
+ const value = parseInt(detailSlider.value);
421
+ let level = "Low";
422
+ if (value > 33) level = "Medium";
423
+ if (value > 66) level = "High";
424
+ detailValue.textContent = level;
425
+ });
426
+
427
  // Image upload preview
428
  const imageUpload = document.getElementById('imageUpload');
429
  const previewCanvas = document.getElementById('previewCanvas');
430
  const ctx = previewCanvas.getContext('2d');
431
+ let uploadedImage = null;
432
 
433
  imageUpload.addEventListener('change', (e) => {
434
  const file = e.target.files[0];
435
  if (file) {
436
  const reader = new FileReader();
437
  reader.onload = (event) => {
438
+ uploadedImage = new Image();
439
+ uploadedImage.onload = () => {
440
  // Calculate dimensions to fit canvas while maintaining aspect ratio
441
  const canvasWidth = previewCanvas.width;
442
  const canvasHeight = previewCanvas.height;
443
+ let width = uploadedImage.width;
444
+ let height = uploadedImage.height;
445
 
446
  if (width > canvasWidth) {
447
  const ratio = canvasWidth / width;
 
460
  const y = (canvasHeight - height) / 2;
461
 
462
  ctx.clearRect(0, 0, canvasWidth, canvasHeight);
463
+ ctx.drawImage(uploadedImage, x, y, width, height);
464
  };
465
+ uploadedImage.src = event.target.result;
466
  };
467
  reader.readAsDataURL(file);
468
  }
469
  });
470
 
471
+ // Generate icon with AI
472
  const generateBtn = document.getElementById('generateBtn');
473
  const loading = document.getElementById('loading');
474
  const resultContainer = document.getElementById('resultContainer');
 
479
  const size48Preview = document.getElementById('size48Preview');
480
  const size64Preview = document.getElementById('size64Preview');
481
  const svgCode = document.getElementById('svgCode');
482
+ const progressContainer = document.getElementById('progressContainer');
483
+ const progressBar = document.getElementById('progressBar');
484
 
485
+ generateBtn.addEventListener('click', async () => {
486
+ const description = document.getElementById('iconDescription').value;
487
+ if (!description && !uploadedImage) {
488
+ alert("Please provide a description or upload an image");
489
+ return;
490
+ }
491
+
492
  // Show loading state
493
  loading.classList.remove('hidden');
494
  resultContainer.classList.add('hidden');
495
  emptyState.classList.add('hidden');
496
+ progressContainer.classList.remove('hidden');
497
 
498
+ // Get selected options
499
+ const selectedColor = document.querySelector('.color-option.selected').getAttribute('data-color');
500
+ let selectedSize = document.querySelector('.size-option.selected')?.getAttribute('data-size') || customSize.value || '64';
501
+ const creativity = parseInt(creativitySlider.value) / 100;
502
+ const detailLevel = parseInt(detailSlider.value) / 100;
503
+
504
+ try {
505
+ // Simulate progress (in a real app, this would reflect actual model progress)
506
+ let progress = 0;
507
+ const progressInterval = setInterval(() => {
508
+ progress += Math.random() * 10;
509
+ if (progress > 90) progress = 90; // Don't go to 100% until done
510
+ progressBar.style.width = `${progress}%`;
511
+ }, 300);
512
 
513
+ // Generate icon with AI (simulated here - in reality you'd call tracrModel.generate())
514
+ let iconMarkup;
515
+ if (uploadedImage) {
516
+ // For image input, we'd normally process the image with the model
517
+ // This is a simplified simulation
518
+ iconMarkup = await generateFromImage(uploadedImage, selectedColor, creativity, detailLevel);
519
+ } else {
520
+ // For text input, generate based on description
521
+ iconMarkup = await generateFromDescription(description, selectedColor, creativity, detailLevel);
522
+ }
523
 
524
+ clearInterval(progressInterval);
525
+ progressBar.style.width = "100%";
526
 
527
+ // Small delay to show completion
528
+ setTimeout(() => {
529
+ loading.classList.add('hidden');
530
+ progressContainer.classList.add('hidden');
531
+ resultContainer.classList.remove('hidden');
532
+
533
+ // Update all previews
534
+ generatedIcon.innerHTML = iconMarkup;
535
+ size16Preview.innerHTML = iconMarkup;
536
+ size32Preview.innerHTML = iconMarkup;
537
+ size48Preview.innerHTML = iconMarkup;
538
+ size64Preview.innerHTML = iconMarkup;
539
+
540
+ // Update SVG code display
541
+ svgCode.textContent = `<svg width="${selectedSize}" height="${selectedSize}" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">\n${iconMarkup}\n</svg>`;
542
+ }, 500);
543
 
544
+ } catch (error) {
545
+ console.error("Error generating icon:", error);
546
+ loading.classList.add('hidden');
547
+ progressContainer.classList.add('hidden');
548
+ alert("Error generating icon. Please try again.");
549
+ }
550
  });
551
 
552
+ // Simulated AI generation from description
553
+ async function generateFromDescription(description, color, creativity, detail) {
554
+ // In a real app, this would call tracrModel.generateSvgFromText()
555
+ // Here we simulate with a simple SVG generator
556
+
557
+ // Analyze keywords in description
558
+ const keywords = {
559
+ animal: description.match(/\b(cat|dog|bird|fish|lion|tiger|elephant|bear)\b/i),
560
+ tech: description.match(/\b(tech|computer|phone|app|code|digital)\b/i),
561
+ nature: description.match(/\b(tree|leaf|flower|mountain|sun|cloud)\b/i),
562
+ food: description.match(/\b(food|pizza|burger|coffee|fruit|vegetable)\b/i),
563
+ business: description.match(/\b(business|finance|money|bank|growth|chart)\b/i)
564
+ };
565
+
566
+ // Determine icon complexity based on detail level
567
+ const complexity = Math.max(1, Math.floor(detail * 4));
568
+
569
+ // Generate appropriate icon based on keywords
570
+ if (keywords.animal) {
571
+ return generateAnimalIcon(keywords.animal[0].toLowerCase(), color, complexity, creativity);
572
+ } else if (keywords.tech) {
573
+ return generateTechIcon(color, complexity, creativity);
574
+ } else if (keywords.nature) {
575
+ return generateNatureIcon(keywords.nature[0].toLowerCase(), color, complexity, creativity);
576
+ } else if (keywords.food) {
577
+ return generateFoodIcon(keywords.food[0].toLowerCase(), color, complexity, creativity);
578
+ } else if (keywords.business) {
579
+ return generateBusinessIcon(color, complexity, creativity);
580
+ } else {
581
+ // Default geometric icon
582
+ return generateGeometricIcon(color, complexity, creativity);
583
+ }
584
+ }
585
+
586
+ // Simulated AI generation from image
587
+ async function generateFromImage(image, color, creativity, detail) {
588
+ // In a real app, this would:
589
+ // 1. Process the image with the model to extract key features
590
+ // 2. Generate a simplified vector version
591
+ // Here we simulate with a simple SVG generator
592
+
593
+ // Create a canvas to analyze the image
594
+ const canvas = document.createElement('canvas');
595
+ canvas.width = 64;
596
+ canvas.height = 64;
597
+ const ctx = canvas.getContext('2d');
598
+ ctx.drawImage(image, 0, 0, 64, 64);
599
+
600
+ // Get dominant color (simplified)
601
+ const pixelData = ctx.getImageData(32, 32, 1, 1).data;
602
+ const dominantColor = `rgb(${pixelData[0]}, ${pixelData[1]}, ${pixelData[2]})`;
603
+
604
+ // Determine if image is more circular or rectangular
605
+ const edgeData = ctx.getImageData(0, 0, 64, 64).data;
606
+ let edgeCount = 0;
607
+ for (let i = 0; i < edgeData.length; i += 4) {
608
+ if (edgeData[i] < 200 || edgeData[i+1] < 200 || edgeData[i+2] < 200) {
609
+ edgeCount++;
610
+ }
611
+ }
612
+ const isRound = edgeCount / (64*64) > 0.7;
613
+
614
+ // Generate appropriate icon based on image characteristics
615
+ if (isRound) {
616
+ return generateRoundIcon(color, detail, creativity);
617
+ } else {
618
+ return generateAngularIcon(color, detail, creativity);
619
+ }
620
+ }
621
+
622
+ // Helper functions to generate different icon types
623
+ function generateAnimalIcon(animal, color, complexity, creativity) {
624
+ const animals = {
625
+ cat: `<path d="M32 20C28 20 24 24 24 28C24 32 28 36 32 36C36 36 40 32 40 28C40 24 36 20 32 20Z" fill="${color}"/>
626
+ <circle cx="28" cy="26" r="2" fill="white"/>
627
+ <circle cx="36" cy="26" r="2" fill="white"/>
628
+ <path d="M30 32C30 33 31 34 32 34C33 34 34 33 34 32" stroke="white" stroke-width="2" fill="none"/>`,
629
+ dog: `<path d="M28 20L36 20L40 28L36 36L28 36L24 28Z" fill="${color}"/>
630
+ <circle cx="32" cy="26" r="2" fill="white"/>
631
+ <path d="M30 32C30 33 31 34 32 34C33 34 34 33 34 32" stroke="white" stroke-width="2" fill="none"/>`,
632
+ bird: `<path d="M24 24C24 28 28 32 32 32C36 32 40 28 40 24" fill="${color}"/>
633
+ <path d="M32 20L40 24L32 28" fill="${color}"/>`
634
+ };
635
+
636
+ return animals[animal] || generateGeometricIcon(color, complexity, creativity);
637
+ }
638
+
639
+ function generateTechIcon(color, complexity, creativity) {
640
+ const techIcons = [
641
+ `<rect x="20" y="20" width="24" height="24" rx="4" fill="${color}"/>
642
+ <rect x="26" y="26" width="12" height="12" fill="white"/>`,
643
+ `<path d="M32 16L48 24L32 32L16 24Z" fill="${color}"/>
644
+ <circle cx="32" cy="24" r="4" fill="white"/>`,
645
+ `<circle cx="32" cy="32" r="12" fill="${color}"/>
646
+ <path d="M32 20L38 32L32 44L26 32Z" fill="white"/>`
647
  ];
648
 
649
+ return techIcons[Math.floor(Math.random() * techIcons.length)];
650
+ }
651
+
652
+ function generateGeometricIcon(color, complexity, creativity) {
653
+ const shapes = [
654
+ () => `<circle cx="32" cy="32" r="${12 + creativity*12}" fill="${color}"/>`,
655
+ () => `<rect x="${20 - creativity*4}" y="${20 - creativity*4}" width="${24 + creativity*8}" height="${24 + creativity*8}" rx="${4 + creativity*4}" fill="${color}"/>`,
656
+ () => `<path d="M32 ${16 - creativity*8}L${48 + creativity*4} ${24 - creativity*4}L${32} ${32 + creativity*8}L${16 - creativity*4} ${24 - creativity*4}Z" fill="${color}"/>`,
657
+ () => `<path d="M${20 - creativity*4} ${20 - creativity*4}L${44 + creativity*4} ${20 - creativity*4}L${44 + creativity*4} ${44 + creativity*4}L${20 - creativity*4} ${44 + creativity*4}Z" fill="${color}"/>`
658
+ ];
659
+
660
+ // Combine shapes based on complexity
661
+ let markup = '';
662
+ for (let i = 0; i < complexity; i++) {
663
+ const randomShape = shapes[Math.floor(Math.random() * shapes.length)];
664
+ markup += randomShape();
665
+ }
666
+
667
+ return markup;
668
  }
669
 
670
  // Copy SVG code