by3axap commited on
Commit
531efa3
·
verified ·
1 Parent(s): 796d2d6

Update templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +53 -202
templates/index.html CHANGED
@@ -3,7 +3,7 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>grahpCLIPPER v2</title>
7
  <style>
8
  @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600&family=JetBrains+Mono&display=swap');
9
  :root {
@@ -55,7 +55,6 @@
55
  input[type="color"]::-webkit-color-swatch-wrapper { padding: 0; }
56
  input[type="color"]::-webkit-color-swatch { border: none; border-radius: 0; }
57
 
58
- /* --- New Toggle Buttons --- */
59
  .toggle-container { display: flex; border: 1px solid #000; margin-top: 8px; }
60
  .toggle-btn { flex: 1; text-align: center; font-family: var(--font-mono); font-size: 10px; padding: 8px 0; cursor: pointer; transition: 0.2s; background: white; color: black; text-transform: uppercase;}
61
  .toggle-btn.active { background: black; color: white; }
@@ -113,7 +112,7 @@
113
 
114
  <div class="control-group">
115
  <div class="label-row">
116
- <span>Stagger</span>
117
  <input type="number" class="num-input" id="num-shift_stagger" value="0" step="0.01" min="0" max="1">
118
  </div>
119
  <input type="range" id="shift_stagger" min="0" max="1" step="0.01" value="0">
@@ -129,10 +128,10 @@
129
 
130
  <div class="control-group">
131
  <div class="label-row">
132
- <span>Growth</span>
133
- <input type="number" class="num-input" id="num-growth" value="0" step="0.05" min="0" max="2.0">
134
  </div>
135
- <input type="range" id="growth" min="0" max="2.0" step="0.05" value="0">
136
  </div>
137
 
138
  <div class="control-group" style="margin-top:16px;">
@@ -161,7 +160,7 @@
161
  <div class="control-group" style="margin-top:16px;">
162
  <span style="font-size:10px; color:#aaa; font-family:var(--font-mono); display:block; margin-bottom:4px;">GROWTH TYPE</span>
163
  <select id="growth_type">
164
- <option value="sine">Diagonal Sine (Fixed)</option>
165
  <option value="linear">Linear Gradient</option>
166
  <option value="steps">Segmented Steps</option>
167
  </select>
@@ -173,12 +172,10 @@
173
  <button class="btn-action secondary" id="btn-dl-svg">Download SVG</button>
174
  <button class="btn-action" id="btn-dl-video" disabled>Export MP4</button>
175
  </div>
176
- <div id="status-msg" style="font-size:10px; font-family:var(--font-mono); margin-top:10px; text-align:center;"></div>
177
  </div>
178
 
179
  <div class="preview-area" id="preview-wrapper">
180
  <canvas id="main-canvas" width="1400" height="900"></canvas>
181
-
182
  <img id="source-image" src="" crossorigin="anonymous">
183
  <video id="source-video" src="" playsinline loop muted crossorigin="anonymous"></video>
184
  <canvas id="helper-canvas" style="display:none;"></canvas>
@@ -192,7 +189,6 @@
192
  let animationId = null;
193
  let customShapeLoaded = false;
194
  let cachedShapeCanvas = null;
195
- let lastFillColor = "#000000";
196
 
197
  // --- DOM ---
198
  const canvas = document.getElementById('main-canvas');
@@ -234,33 +230,24 @@
234
  x.fillStyle = color;
235
  x.fillRect(0, 0, c.width, c.height);
236
  cachedShapeCanvas = c;
237
- lastFillColor = color;
238
  }
239
 
240
  // --- EVENT LISTENERS ---
241
- // 1. Direction Toggles
242
  const btnDirH = document.getElementById('btn-dir-h');
243
  const btnDirV = document.getElementById('btn-dir-v');
244
  const inputDir = document.getElementById('direction');
245
 
246
  const setDirection = (dir) => {
247
  inputDir.value = dir;
248
- if(dir === 'horizontal') {
249
- btnDirH.classList.add('active');
250
- btnDirV.classList.remove('active');
251
- } else {
252
- btnDirV.classList.add('active');
253
- btnDirH.classList.remove('active');
254
- }
255
  requestRender();
256
  };
257
 
258
  btnDirH.addEventListener('click', () => setDirection('horizontal'));
259
  btnDirV.addEventListener('click', () => setDirection('vertical'));
260
 
261
- // 2. Shape Upload
262
- const shapeInput = document.getElementById('shape_svg');
263
- shapeInput.addEventListener('change', (e) => {
264
  const file = e.target.files[0];
265
  if(!file) return;
266
  setBtnState('lbl-shape', 'rm-shape', file, true);
@@ -276,61 +263,27 @@
276
  };
277
  reader.readAsText(file);
278
  });
279
-
280
- document.getElementById('rm-shape').addEventListener('click', () => {
281
- shapeInput.value = '';
282
- customShapeLoaded = false;
283
- shapeImg.src = '';
284
- cachedShapeCanvas = null;
285
- setBtnState('lbl-shape', 'rm-shape', null, false);
286
- requestRender();
287
- });
288
 
289
- // 3. Content Upload
290
- const contentInput = document.getElementById('content_file');
291
- contentInput.addEventListener('change', (e) => {
292
  const file = e.target.files[0];
293
  if(!file) return;
294
  currentFile = file;
295
  setBtnState('lbl-content', 'rm-content', file, true);
296
  const url = URL.createObjectURL(file);
297
- const type = file.type;
298
-
299
- sourceImage.src = "";
300
- sourceVideo.src = "";
301
- sourceVideo.pause();
302
-
303
- if (type.startsWith('image/')) {
304
  currentMode = 'image';
305
  sourceImage.src = url;
306
  sourceImage.onload = () => requestRender();
307
  document.getElementById('btn-dl-video').disabled = true;
308
- document.getElementById('btn-dl-svg').disabled = false;
309
- }
310
- else if (type.startsWith('video/')) {
311
  currentMode = 'video';
312
  sourceVideo.src = url;
313
  sourceVideo.play();
314
  document.getElementById('btn-dl-video').disabled = false;
315
- document.getElementById('btn-dl-svg').disabled = true;
316
  requestRender();
317
  }
318
  });
319
-
320
- document.getElementById('rm-content').addEventListener('click', () => {
321
- contentInput.value = '';
322
- currentFile = null;
323
- sourceImage.src = "";
324
- sourceVideo.src = "";
325
- sourceVideo.pause();
326
- setBtnState('lbl-content', 'rm-content', null, false);
327
- currentMode = 'image';
328
- document.getElementById('btn-dl-video').disabled = true;
329
- document.getElementById('btn-dl-svg').disabled = false;
330
- requestRender();
331
- });
332
 
333
- // 4. Inputs Sync
334
  const paramIds = ['density', 'gap_x', 'gap_y', 'shift_stagger', 'base_scale', 'growth'];
335
  paramIds.forEach(id => {
336
  const slider = document.getElementById(id);
@@ -338,19 +291,15 @@
338
  slider.addEventListener('input', () => { number.value = slider.value; requestRender(); });
339
  number.addEventListener('input', () => { slider.value = number.value; requestRender(); });
340
  });
 
341
  document.getElementById('invert').addEventListener('change', requestRender);
342
  document.getElementById('growth_type').addEventListener('change', requestRender);
343
-
344
- // 5. Colors
345
- const bgColorInput = document.getElementById('bg_color');
346
- const fillColorInput = document.getElementById('fill_color');
347
- bgColorInput.addEventListener('input', () => {
348
- previewWrapper.style.backgroundColor = bgColorInput.value;
349
  requestRender();
350
  });
351
- fillColorInput.addEventListener('input', () => {
352
- const color = fillColorInput.value;
353
- if(customShapeLoaded) updateCachedShape(color);
354
  requestRender();
355
  });
356
 
@@ -373,10 +322,7 @@
373
  }
374
 
375
  function drawFrame() {
376
- const w = canvas.width;
377
- const h = canvas.height;
378
-
379
- // Params
380
  const density = parseInt(document.getElementById('density').value);
381
  const gapX = parseFloat(document.getElementById('gap_x').value);
382
  const gapY = parseFloat(document.getElementById('gap_y').value);
@@ -386,98 +332,67 @@
386
  const growthType = document.getElementById('growth_type').value;
387
  const direction = document.getElementById('direction').value;
388
  const invert = document.getElementById('invert').checked;
389
- const bgColor = bgColorInput.value;
390
- const fillColor = fillColorInput.value;
391
 
392
- // Clear
393
- ctx.fillStyle = bgColor;
394
  ctx.fillRect(0, 0, w, h);
395
 
396
- // Read Pixel Data
397
  let sourceData = null;
398
- let sw = 0;
399
  let activeSource = (currentMode === 'video') ? sourceVideo : sourceImage;
400
- let ready = false;
401
- if(currentMode === 'image' && sourceImage.src) ready = true;
402
- if(currentMode === 'video' && sourceVideo.readyState >= 2) ready = true;
403
 
404
  if (ready) {
405
- helperCanvas.width = w;
406
- helperCanvas.height = h;
407
  helperCtx.drawImage(activeSource, 0, 0, w, h);
408
- const imgData = helperCtx.getImageData(0, 0, w, h);
409
- sourceData = imgData.data;
410
- sw = w;
411
  }
412
 
413
- // Draw Grid
414
- ctx.fillStyle = fillColor;
415
-
416
  const step = w / density;
417
  const rows = Math.ceil(h / step);
418
  const cellWMax = step * (1.0 - gapX);
419
  const cellHMax = step * (1.0 - gapY);
420
-
421
- const startC = -Math.floor(density * 0.2);
422
- const endC = density * 1.2;
423
 
424
  for (let r = 0; r < rows; r++) {
425
  const rowShift = (r * stagger * step);
426
-
427
- for (let c = startC; c < endC; c++) {
428
  const gridX = c * step + rowShift;
429
  const gridY = r * step;
430
-
431
  if (gridX < -step || gridX > w) continue;
432
 
433
- // 1. Brightness
434
  let isVisible = true;
435
  if (sourceData) {
436
  const sx = Math.max(0, Math.min(Math.floor(gridX + step/2), w - 1));
437
  const sy = Math.max(0, Math.min(Math.floor(gridY + step/2), h - 1));
438
- const idx = (sy * sw + sx) * 4;
439
- const rV = sourceData[idx];
440
- const gV = sourceData[idx+1];
441
- const bV = sourceData[idx+2];
442
- const bright = (rV + gV + bV) / 3 / 255.0;
443
-
444
- const limit = 0.5;
445
- isVisible = invert ? (bright > limit) : (bright < limit);
446
  }
447
  if (!isVisible) continue;
448
 
449
- // 2. Growth (UPDATED JS LOGIC)
450
  const normX = gridX / w;
451
  const normY = gridY / h;
452
-
453
- // Главная ось
454
  const t = (direction === 'vertical') ? normY : normX;
455
 
456
  let wave = 0;
457
  if (growthType === 'sine') {
458
- // Диагональ, независящая от плотности
459
- wave = (Math.sin((normX + normY) * Math.PI) + 1) / 2;
460
- }
461
- else if (growthType === 'linear') {
462
  wave = t;
463
- }
464
- else if (growthType === 'steps') {
465
- const segments = 6.0;
466
- wave = Math.floor(t * segments) / segments;
467
  }
468
 
469
- let modW = 1.0 - (wave * growth);
470
- modW = Math.max(0.01, Math.min(1.0, modW));
471
-
472
  const contentW = cellWMax * baseScale * modW;
473
  const contentH = cellHMax * baseScale;
474
-
475
- const cx = gridX + step/2;
476
- const cy = gridY + step/2;
477
 
478
  ctx.save();
479
- ctx.translate(cx, cy);
480
-
481
  if (customShapeLoaded && cachedShapeCanvas) {
482
  ctx.drawImage(cachedShapeCanvas, -contentW/2, -contentH/2, contentW, contentH);
483
  } else {
@@ -487,85 +402,21 @@
487
  }
488
  }
489
  }
490
-
491
- // --- EXPORT ---
492
- document.getElementById('btn-dl-svg').addEventListener('click', async () => {
493
- const btn = document.getElementById('btn-dl-svg');
494
- const originalText = btn.innerText;
495
- btn.innerText = "Processing...";
496
- btn.disabled = true;
497
-
498
- const form = new FormData();
499
- paramIds.forEach(id => form.append(id, document.getElementById(id).value));
500
- form.append('growth_type', document.getElementById('growth_type').value);
501
- form.append('direction', document.getElementById('direction').value);
502
- form.append('invert', document.getElementById('invert').checked);
503
- form.append('bg_color', document.getElementById('bg_color').value);
504
- form.append('fill_color', document.getElementById('fill_color').value);
505
-
506
- if (customShapeLoaded) {
507
- const fileInput = document.getElementById('shape_svg');
508
- if(fileInput.files[0]) form.append('shape_svg', fileInput.files[0]);
509
- }
510
- if (currentMode === 'image' && currentFile) {
511
- form.append('raster_image', currentFile);
512
- }
513
-
514
- try {
515
- const resp = await fetch('/download_svg', { method: 'POST', body: form });
516
- if (!resp.ok) throw new Error(await resp.text());
517
- const blob = await resp.blob();
518
- const url = window.URL.createObjectURL(blob);
519
- const a = document.createElement('a');
520
- a.href = url;
521
- a.download = "pattern.svg";
522
- document.body.appendChild(a);
523
- a.click();
524
- document.body.removeChild(a);
525
- } catch (e) {
526
- alert("Error: " + e.message);
527
- } finally {
528
- btn.innerText = originalText;
529
- btn.disabled = false;
530
- }
531
- });
532
-
533
- document.getElementById('btn-dl-video').addEventListener('click', async () => {
534
- const btn = document.getElementById('btn-dl-video');
535
- const originalText = btn.innerText;
536
- btn.innerText = "Rendering...";
537
- btn.disabled = true;
538
-
539
- const form = new FormData();
540
- paramIds.forEach(id => form.append(id, document.getElementById(id).value));
541
- form.append('growth_type', document.getElementById('growth_type').value);
542
- form.append('direction', document.getElementById('direction').value);
543
- form.append('invert', document.getElementById('invert').checked);
544
- form.append('bg_color', document.getElementById('bg_color').value);
545
- form.append('fill_color', document.getElementById('fill_color').value);
546
-
547
- if (currentMode === 'video' && currentFile) {
548
- form.append('video_file', currentFile);
549
- }
550
-
551
- try {
552
- const resp = await fetch('/process_video', { method: 'POST', body: form });
553
- if (!resp.ok) throw new Error(await resp.text());
554
- const blob = await resp.blob();
555
- const url = window.URL.createObjectURL(blob);
556
- const a = document.createElement('a');
557
- a.href = url;
558
- a.download = "processed.mp4";
559
- document.body.appendChild(a);
560
- a.click();
561
- document.body.removeChild(a);
562
- } catch (e) {
563
- alert("Error: " + e.message);
564
- } finally {
565
- btn.innerText = originalText;
566
- btn.disabled = false;
567
- }
568
- });
569
  </script>
570
  </body>
571
  </html>
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>grahpCLIPPER v2.1</title>
7
  <style>
8
  @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600&family=JetBrains+Mono&display=swap');
9
  :root {
 
55
  input[type="color"]::-webkit-color-swatch-wrapper { padding: 0; }
56
  input[type="color"]::-webkit-color-swatch { border: none; border-radius: 0; }
57
 
 
58
  .toggle-container { display: flex; border: 1px solid #000; margin-top: 8px; }
59
  .toggle-btn { flex: 1; text-align: center; font-family: var(--font-mono); font-size: 10px; padding: 8px 0; cursor: pointer; transition: 0.2s; background: white; color: black; text-transform: uppercase;}
60
  .toggle-btn.active { background: black; color: white; }
 
112
 
113
  <div class="control-group">
114
  <div class="label-row">
115
+ <span>Stagger (Loop)</span>
116
  <input type="number" class="num-input" id="num-shift_stagger" value="0" step="0.01" min="0" max="1">
117
  </div>
118
  <input type="range" id="shift_stagger" min="0" max="1" step="0.01" value="0">
 
128
 
129
  <div class="control-group">
130
  <div class="label-row">
131
+ <span>Growth Amount</span>
132
+ <input type="number" class="num-input" id="num-growth" value="0.5" step="0.05" min="0" max="2.0">
133
  </div>
134
+ <input type="range" id="growth" min="0" max="2.0" step="0.05" value="0.5">
135
  </div>
136
 
137
  <div class="control-group" style="margin-top:16px;">
 
160
  <div class="control-group" style="margin-top:16px;">
161
  <span style="font-size:10px; color:#aaa; font-family:var(--font-mono); display:block; margin-bottom:4px;">GROWTH TYPE</span>
162
  <select id="growth_type">
163
+ <option value="sine">Diagonal Sine (Bottom-Left to Top-Right)</option>
164
  <option value="linear">Linear Gradient</option>
165
  <option value="steps">Segmented Steps</option>
166
  </select>
 
172
  <button class="btn-action secondary" id="btn-dl-svg">Download SVG</button>
173
  <button class="btn-action" id="btn-dl-video" disabled>Export MP4</button>
174
  </div>
 
175
  </div>
176
 
177
  <div class="preview-area" id="preview-wrapper">
178
  <canvas id="main-canvas" width="1400" height="900"></canvas>
 
179
  <img id="source-image" src="" crossorigin="anonymous">
180
  <video id="source-video" src="" playsinline loop muted crossorigin="anonymous"></video>
181
  <canvas id="helper-canvas" style="display:none;"></canvas>
 
189
  let animationId = null;
190
  let customShapeLoaded = false;
191
  let cachedShapeCanvas = null;
 
192
 
193
  // --- DOM ---
194
  const canvas = document.getElementById('main-canvas');
 
230
  x.fillStyle = color;
231
  x.fillRect(0, 0, c.width, c.height);
232
  cachedShapeCanvas = c;
 
233
  }
234
 
235
  // --- EVENT LISTENERS ---
 
236
  const btnDirH = document.getElementById('btn-dir-h');
237
  const btnDirV = document.getElementById('btn-dir-v');
238
  const inputDir = document.getElementById('direction');
239
 
240
  const setDirection = (dir) => {
241
  inputDir.value = dir;
242
+ btnDirH.classList.toggle('active', dir === 'horizontal');
243
+ btnDirV.classList.toggle('active', dir === 'vertical');
 
 
 
 
 
244
  requestRender();
245
  };
246
 
247
  btnDirH.addEventListener('click', () => setDirection('horizontal'));
248
  btnDirV.addEventListener('click', () => setDirection('vertical'));
249
 
250
+ document.getElementById('shape_svg').addEventListener('change', (e) => {
 
 
251
  const file = e.target.files[0];
252
  if(!file) return;
253
  setBtnState('lbl-shape', 'rm-shape', file, true);
 
263
  };
264
  reader.readAsText(file);
265
  });
 
 
 
 
 
 
 
 
 
266
 
267
+ document.getElementById('content_file').addEventListener('change', (e) => {
 
 
268
  const file = e.target.files[0];
269
  if(!file) return;
270
  currentFile = file;
271
  setBtnState('lbl-content', 'rm-content', file, true);
272
  const url = URL.createObjectURL(file);
273
+ if (file.type.startsWith('image/')) {
 
 
 
 
 
 
274
  currentMode = 'image';
275
  sourceImage.src = url;
276
  sourceImage.onload = () => requestRender();
277
  document.getElementById('btn-dl-video').disabled = true;
278
+ } else {
 
 
279
  currentMode = 'video';
280
  sourceVideo.src = url;
281
  sourceVideo.play();
282
  document.getElementById('btn-dl-video').disabled = false;
 
283
  requestRender();
284
  }
285
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
286
 
 
287
  const paramIds = ['density', 'gap_x', 'gap_y', 'shift_stagger', 'base_scale', 'growth'];
288
  paramIds.forEach(id => {
289
  const slider = document.getElementById(id);
 
291
  slider.addEventListener('input', () => { number.value = slider.value; requestRender(); });
292
  number.addEventListener('input', () => { slider.value = number.value; requestRender(); });
293
  });
294
+
295
  document.getElementById('invert').addEventListener('change', requestRender);
296
  document.getElementById('growth_type').addEventListener('change', requestRender);
297
+ document.getElementById('bg_color').addEventListener('input', (e) => {
298
+ previewWrapper.style.backgroundColor = e.target.value;
 
 
 
 
299
  requestRender();
300
  });
301
+ document.getElementById('fill_color').addEventListener('input', (e) => {
302
+ if(customShapeLoaded) updateCachedShape(e.target.value);
 
303
  requestRender();
304
  });
305
 
 
322
  }
323
 
324
  function drawFrame() {
325
+ const w = canvas.width, h = canvas.height;
 
 
 
326
  const density = parseInt(document.getElementById('density').value);
327
  const gapX = parseFloat(document.getElementById('gap_x').value);
328
  const gapY = parseFloat(document.getElementById('gap_y').value);
 
332
  const growthType = document.getElementById('growth_type').value;
333
  const direction = document.getElementById('direction').value;
334
  const invert = document.getElementById('invert').checked;
335
+ const fillColor = document.getElementById('fill_color').value;
 
336
 
337
+ ctx.fillStyle = document.getElementById('bg_color').value;
 
338
  ctx.fillRect(0, 0, w, h);
339
 
 
340
  let sourceData = null;
 
341
  let activeSource = (currentMode === 'video') ? sourceVideo : sourceImage;
342
+ let ready = (currentMode === 'image' && sourceImage.src) || (currentMode === 'video' && sourceVideo.readyState >= 2);
 
 
343
 
344
  if (ready) {
345
+ helperCanvas.width = w; helperCanvas.height = h;
 
346
  helperCtx.drawImage(activeSource, 0, 0, w, h);
347
+ sourceData = helperCtx.getImageData(0, 0, w, h).data;
 
 
348
  }
349
 
 
 
 
350
  const step = w / density;
351
  const rows = Math.ceil(h / step);
352
  const cellWMax = step * (1.0 - gapX);
353
  const cellHMax = step * (1.0 - gapY);
354
+
355
+ ctx.fillStyle = fillColor;
 
356
 
357
  for (let r = 0; r < rows; r++) {
358
  const rowShift = (r * stagger * step);
359
+ for (let c = -Math.floor(density * 0.2); c < density * 1.2; c++) {
 
360
  const gridX = c * step + rowShift;
361
  const gridY = r * step;
 
362
  if (gridX < -step || gridX > w) continue;
363
 
364
+ // Brightness Logic
365
  let isVisible = true;
366
  if (sourceData) {
367
  const sx = Math.max(0, Math.min(Math.floor(gridX + step/2), w - 1));
368
  const sy = Math.max(0, Math.min(Math.floor(gridY + step/2), h - 1));
369
+ const idx = (sy * w + sx) * 4;
370
+ const bright = (sourceData[idx] + sourceData[idx+1] + sourceData[idx+2]) / 3 / 255.0;
371
+ isVisible = invert ? (bright > 0.5) : (bright < 0.5);
 
 
 
 
 
372
  }
373
  if (!isVisible) continue;
374
 
375
+ // NEW ANIMATION LOGIC
376
  const normX = gridX / w;
377
  const normY = gridY / h;
 
 
378
  const t = (direction === 'vertical') ? normY : normX;
379
 
380
  let wave = 0;
381
  if (growthType === 'sine') {
382
+ // Исправленная диагональ
383
+ wave = (Math.sin((normX + (1 - normY)) * Math.PI) + 1) / 2;
384
+ } else if (growthType === 'linear') {
 
385
  wave = t;
386
+ } else {
387
+ wave = Math.floor(t * 6) / 6;
 
 
388
  }
389
 
390
+ let modW = Math.max(0.01, Math.min(1.0, 1.0 - (wave * growth)));
 
 
391
  const contentW = cellWMax * baseScale * modW;
392
  const contentH = cellHMax * baseScale;
 
 
 
393
 
394
  ctx.save();
395
+ ctx.translate(gridX + step/2, gridY + step/2);
 
396
  if (customShapeLoaded && cachedShapeCanvas) {
397
  ctx.drawImage(cachedShapeCanvas, -contentW/2, -contentH/2, contentW, contentH);
398
  } else {
 
402
  }
403
  }
404
  }
405
+
406
+ // Скрипты для удаления и экспорта (заглушки или fetch как в оригинале)
407
+ document.getElementById('rm-shape').onclick = () => {
408
+ document.getElementById('shape_svg').value = '';
409
+ customShapeLoaded = false;
410
+ setBtnState('lbl-shape', 'rm-shape', null, false);
411
+ requestRender();
412
+ };
413
+ document.getElementById('rm-content').onclick = () => {
414
+ document.getElementById('content_file').value = '';
415
+ currentFile = null;
416
+ sourceImage.src = sourceVideo.src = '';
417
+ setBtnState('lbl-content', 'rm-content', null, false);
418
+ requestRender();
419
+ };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
420
  </script>
421
  </body>
422
  </html>