pg0 commited on
Commit
d9cb1f6
·
verified ·
1 Parent(s): 12e5499

Add 1 files

Browse files
Files changed (1) hide show
  1. index.html +290 -1
index.html CHANGED
@@ -15,6 +15,10 @@
15
  border-color: #4f46e5;
16
  background-color: #eef2ff;
17
  }
 
 
 
 
18
  .progress-bar {
19
  transition: width 0.3s ease;
20
  }
@@ -51,6 +55,9 @@
51
  visibility: visible;
52
  opacity: 1;
53
  }
 
 
 
54
  </style>
55
  </head>
56
  <body class="bg-gray-50 min-h-screen">
@@ -69,7 +76,7 @@
69
  <!-- Left Panel - Upload and Settings -->
70
  <div class="p-6 md:w-1/2 border-r border-gray-200">
71
  <div id="dropzone" class="dropzone rounded-lg p-8 text-center cursor-pointer mb-6">
72
- <div class="flex flex-col items-center justify-center">
73
  <i class="fas fa-cloud-upload-alt text-4xl text-indigo-500 mb-3"></i>
74
  <h3 class="text-lg font-medium text-gray-700 mb-1">Drag & Drop your image here</h3>
75
  <p class="text-gray-500 text-sm mb-3">or click to browse files</p>
@@ -78,6 +85,15 @@
78
  Select Image
79
  </button>
80
  </div>
 
 
 
 
 
 
 
 
 
81
  </div>
82
 
83
  <div id="previewContainer" class="hidden mb-6">
@@ -126,6 +142,10 @@
126
  <input type="checkbox" id="transparentBg" class="h-4 w-4 text-indigo-600 focus:ring-indigo-500 border-gray-300 rounded">
127
  <label for="transparentBg" class="ml-2 block text-sm text-gray-700">Transparent background</label>
128
  </div>
 
 
 
 
129
  </div>
130
  </div>
131
 
@@ -160,5 +180,274 @@
160
  <div>
161
  <div class="flex items-center justify-between mb-2">
162
  <h4 class="text-sm font-medium text-gray-700">SVG Code</h4>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
 
 
 
 
 
 
 
 
164
  </html>
 
15
  border-color: #4f46e5;
16
  background-color: #eef2ff;
17
  }
18
+ .dropzone.error {
19
+ border-color: #ef4444;
20
+ background-color: #fee2e2;
21
+ }
22
  .progress-bar {
23
  transition: width 0.3s ease;
24
  }
 
55
  visibility: visible;
56
  opacity: 1;
57
  }
58
+ .file-info {
59
+ display: none;
60
+ }
61
  </style>
62
  </head>
63
  <body class="bg-gray-50 min-h-screen">
 
76
  <!-- Left Panel - Upload and Settings -->
77
  <div class="p-6 md:w-1/2 border-r border-gray-200">
78
  <div id="dropzone" class="dropzone rounded-lg p-8 text-center cursor-pointer mb-6">
79
+ <div id="uploadUI" class="flex flex-col items-center justify-center">
80
  <i class="fas fa-cloud-upload-alt text-4xl text-indigo-500 mb-3"></i>
81
  <h3 class="text-lg font-medium text-gray-700 mb-1">Drag & Drop your image here</h3>
82
  <p class="text-gray-500 text-sm mb-3">or click to browse files</p>
 
85
  Select Image
86
  </button>
87
  </div>
88
+ <div id="fileInfo" class="file-info flex items-center justify-center">
89
+ <div class="bg-gray-100 rounded-lg p-3 flex items-center">
90
+ <i class="fas fa-file-image text-indigo-500 text-xl mr-3"></i>
91
+ <div>
92
+ <p id="fileName" class="text-sm font-medium text-gray-700 truncate max-w-xs"></p>
93
+ <p id="fileSize" class="text-xs text-gray-500"></p>
94
+ </div>
95
+ </div>
96
+ </div>
97
  </div>
98
 
99
  <div id="previewContainer" class="hidden mb-6">
 
142
  <input type="checkbox" id="transparentBg" class="h-4 w-4 text-indigo-600 focus:ring-indigo-500 border-gray-300 rounded">
143
  <label for="transparentBg" class="ml-2 block text-sm text-gray-700">Transparent background</label>
144
  </div>
145
+
146
+ <button id="convertBtn" class="w-full bg-indigo-600 hover:bg-indigo-700 text-white py-2 px-4 rounded-md font-medium transition disabled:opacity-50 disabled:cursor-not-allowed" disabled>
147
+ Convert to SVG
148
+ </button>
149
  </div>
150
  </div>
151
 
 
180
  <div>
181
  <div class="flex items-center justify-between mb-2">
182
  <h4 class="text-sm font-medium text-gray-700">SVG Code</h4>
183
+ <button id="copyCodeBtn" class="text-indigo-600 hover:text-indigo-800 text-xs font-medium">
184
+ <i class="fas fa-copy mr-1"></i> Copy Code
185
+ </button>
186
+ </div>
187
+ <pre id="svgCode" class="bg-gray-800 text-gray-100 text-xs p-3 rounded-md overflow-auto max-h-40"></pre>
188
+ </div>
189
+ </div>
190
+
191
+ <div id="emptyState" class="text-center py-12">
192
+ <div class="mx-auto w-16 h-16 bg-indigo-100 rounded-full flex items-center justify-center mb-4">
193
+ <i class="fas fa-image text-indigo-500 text-xl"></i>
194
+ </div>
195
+ <h3 class="text-lg font-medium text-gray-700">No image uploaded</h3>
196
+ <p class="text-gray-500 text-sm mt-1">Upload an image to convert it to SVG format</p>
197
+ </div>
198
+ </div>
199
+ </div>
200
+ </div>
201
+
202
+ <footer class="text-center mt-12 text-gray-500 text-sm">
203
+ <p>Image to SVG Vectorizer &copy; 2023 | All rights reserved</p>
204
+ </footer>
205
+ </div>
206
+
207
+ <script>
208
+ document.addEventListener('DOMContentLoaded', function() {
209
+ // DOM elements
210
+ const dropzone = document.getElementById('dropzone');
211
+ const fileInput = document.getElementById('fileInput');
212
+ const browseBtn = document.getElementById('browseBtn');
213
+ const uploadUI = document.getElementById('uploadUI');
214
+ const fileInfo = document.getElementById('fileInfo');
215
+ const fileName = document.getElementById('fileName');
216
+ const fileSize = document.getElementById('fileSize');
217
+ const previewContainer = document.getElementById('previewContainer');
218
+ const imagePreview = document.getElementById('imagePreview');
219
+ const removeImage = document.getElementById('removeImage');
220
+ const convertBtn = document.getElementById('convertBtn');
221
+ const processingUI = document.getElementById('processingUI');
222
+ const progressBar = document.getElementById('progressBar');
223
+ const resultContainer = document.getElementById('resultContainer');
224
+ const emptyState = document.getElementById('emptyState');
225
+ const svgPreview = document.getElementById('svgPreview');
226
+ const svgCode = document.getElementById('svgCode');
227
+ const downloadBtn = document.getElementById('downloadBtn');
228
+ const copyBtn = document.getElementById('copyBtn');
229
+ const copyCodeBtn = document.getElementById('copyCodeBtn');
230
+
231
+ // Prevent default drag behaviors
232
+ ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
233
+ dropzone.addEventListener(eventName, preventDefaults, false);
234
+ document.body.addEventListener(eventName, preventDefaults, false);
235
+ });
236
+
237
+ function preventDefaults(e) {
238
+ e.preventDefault();
239
+ e.stopPropagation();
240
+ }
241
+
242
+ // Highlight dropzone when item is dragged over it
243
+ ['dragenter', 'dragover'].forEach(eventName => {
244
+ dropzone.addEventListener(eventName, highlight, false);
245
+ });
246
+
247
+ ['dragleave', 'drop'].forEach(eventName => {
248
+ dropzone.addEventListener(eventName, unhighlight, false);
249
+ });
250
+
251
+ function highlight() {
252
+ dropzone.classList.add('active');
253
+ }
254
+
255
+ function unhighlight() {
256
+ dropzone.classList.remove('active');
257
+ }
258
+
259
+ // Handle dropped files
260
+ dropzone.addEventListener('drop', handleDrop, false);
261
+
262
+ function handleDrop(e) {
263
+ const dt = e.dataTransfer;
264
+ const files = dt.files;
265
+ handleFiles(files);
266
+ }
267
+
268
+ // Handle file selection via button
269
+ browseBtn.addEventListener('click', () => {
270
+ fileInput.click();
271
+ });
272
+
273
+ fileInput.addEventListener('change', () => {
274
+ if (fileInput.files.length) {
275
+ handleFiles(fileInput.files);
276
+ }
277
+ });
278
+
279
+ // Remove image
280
+ removeImage.addEventListener('click', resetUpload);
281
+
282
+ // Convert button
283
+ convertBtn.addEventListener('click', processImage);
284
+
285
+ // Copy buttons
286
+ copyBtn.addEventListener('click', copySVG);
287
+ copyCodeBtn.addEventListener('click', copySVGCode);
288
+
289
+ // Download button
290
+ downloadBtn.addEventListener('click', downloadSVG);
291
+
292
+ // Handle selected files
293
+ function handleFiles(files) {
294
+ const file = files[0];
295
+
296
+ // Check if file is an image
297
+ if (!file.type.match('image.*')) {
298
+ showError('Please upload an image file (JPG, PNG, etc.)');
299
+ return;
300
+ }
301
+
302
+ // Check file size (max 5MB)
303
+ if (file.size > 5 * 1024 * 1024) {
304
+ showError('File size exceeds 5MB limit');
305
+ return;
306
+ }
307
+
308
+ // Display file info
309
+ uploadUI.style.display = 'none';
310
+ fileInfo.style.display = 'flex';
311
+ fileName.textContent = file.name;
312
+ fileSize.textContent = formatFileSize(file.size);
313
+
314
+ // Display image preview
315
+ const reader = new FileReader();
316
+ reader.onload = function(e) {
317
+ imagePreview.src = e.target.result;
318
+ previewContainer.classList.remove('hidden');
319
+ convertBtn.disabled = false;
320
+ };
321
+ reader.readAsDataURL(file);
322
+ }
323
+
324
+ // Format file size
325
+ function formatFileSize(bytes) {
326
+ if (bytes < 1024) return bytes + ' bytes';
327
+ else if (bytes < 1048576) return (bytes / 1024).toFixed(1) + ' KB';
328
+ else return (bytes / 1048576).toFixed(1) + ' MB';
329
+ }
330
+
331
+ // Show error message
332
+ function showError(message) {
333
+ dropzone.classList.add('error');
334
+ const errorElement = document.createElement('div');
335
+ errorElement.className = 'text-red-500 text-sm mt-2';
336
+ errorElement.textContent = message;
337
+ dropzone.appendChild(errorElement);
338
+
339
+ setTimeout(() => {
340
+ dropzone.classList.remove('error');
341
+ dropzone.removeChild(errorElement);
342
+ }, 3000);
343
+ }
344
+
345
+ // Reset upload
346
+ function resetUpload() {
347
+ fileInput.value = '';
348
+ uploadUI.style.display = 'flex';
349
+ fileInfo.style.display = 'none';
350
+ previewContainer.classList.add('hidden');
351
+ convertBtn.disabled = true;
352
+ emptyState.classList.remove('hidden');
353
+ resultContainer.classList.add('hidden');
354
+ }
355
+
356
+ // Process image (simulated)
357
+ function processImage() {
358
+ // Show processing UI
359
+ processingUI.classList.remove('hidden');
360
+ emptyState.classList.add('hidden');
361
+ resultContainer.classList.add('hidden');
362
+
363
+ // Simulate processing with progress
364
+ let progress = 0;
365
+ const interval = setInterval(() => {
366
+ progress += Math.random() * 10;
367
+ if (progress > 100) progress = 100;
368
+ progressBar.style.width = progress + '%';
369
+
370
+ if (progress === 100) {
371
+ clearInterval(interval);
372
+ setTimeout(showResult, 500);
373
+ }
374
+ }, 300);
375
+ }
376
+
377
+ // Show result
378
+ function showResult() {
379
+ processingUI.classList.add('hidden');
380
+ resultContainer.classList.remove('hidden');
381
+ emptyState.classList.add('hidden');
382
+ downloadBtn.classList.remove('hidden');
383
+ copyBtn.classList.remove('hidden');
384
+
385
+ // Generate sample SVG (in a real app, this would come from your vectorization process)
386
+ const sampleSVG = generateSampleSVG(imagePreview.src);
387
+ svgPreview.innerHTML = sampleSVG;
388
+ svgCode.textContent = sampleSVG;
389
+ }
390
+
391
+ // Generate sample SVG (for demo purposes)
392
+ function generateSampleSVG(imageSrc) {
393
+ return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
394
+ <rect width="200" height="200" fill="#f0f0f0"/>
395
+ <circle cx="100" cy="100" r="80" fill="#4f46e5" opacity="0.8"/>
396
+ <path d="M100 50 L120 150 L80 150 Z" fill="#ffffff" stroke="#333" stroke-width="2"/>
397
+ <text x="100" y="120" font-family="Arial" font-size="24" fill="#ffffff" text-anchor="middle">SVG</text>
398
+ </svg>`;
399
+ }
400
+
401
+ // Copy SVG to clipboard
402
+ function copySVG() {
403
+ const svg = svgPreview.innerHTML;
404
+ navigator.clipboard.writeText(svg)
405
+ .then(() => {
406
+ showTooltip(copyBtn, 'SVG copied to clipboard!');
407
+ })
408
+ .catch(err => {
409
+ console.error('Failed to copy SVG: ', err);
410
+ });
411
+ }
412
+
413
+ // Copy SVG code to clipboard
414
+ function copySVGCode() {
415
+ const code = svgCode.textContent;
416
+ navigator.clipboard.writeText(code)
417
+ .then(() => {
418
+ showTooltip(copyCodeBtn, 'Code copied to clipboard!');
419
+ })
420
+ .catch(err => {
421
+ console.error('Failed to copy code: ', err);
422
+ });
423
+ }
424
+
425
+ // Download SVG
426
+ function downloadSVG() {
427
+ const svg = svgPreview.innerHTML;
428
+ const blob = new Blob([svg], {type: 'image/svg+xml'});
429
+ const url = URL.createObjectURL(blob);
430
+ const a = document.createElement('a');
431
+ a.href = url;
432
+ a.download = fileName.textContent.replace(/\.[^/.]+$/, "") + '.svg';
433
+ document.body.appendChild(a);
434
+ a.click();
435
+ document.body.removeChild(a);
436
+ URL.revokeObjectURL(url);
437
+ }
438
+
439
+ // Show tooltip
440
+ function showTooltip(element, message) {
441
+ const tooltip = document.createElement('div');
442
+ tooltip.className = 'absolute bg-gray-800 text-white text-xs px-2 py-1 rounded -mt-8';
443
+ tooltip.textContent = message;
444
+ element.appendChild(tooltip);
445
 
446
+ setTimeout(() => {
447
+ element.removeChild(tooltip);
448
+ }, 2000);
449
+ }
450
+ });
451
+ </script>
452
+ <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=pg0/vectorizer" style="color: #fff;text-decoration: underline;" target="_blank" >🧬 Remix</a></p></body>
453
  </html>