jhh6576 commited on
Commit
52a8ead
·
verified ·
1 Parent(s): f920d28

Update app_enhanced.py

Browse files
Files changed (1) hide show
  1. app_enhanced.py +82 -39
app_enhanced.py CHANGED
@@ -496,7 +496,7 @@ class EnhancedComicGenerator:
496
  <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
497
  <link rel="preconnect" href="https://fonts.googleapis.com">
498
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
499
- <link href="https://fonts.googleapis.com/css2?family=Bangers&family=Comic+Neue:wght@700&family=Gloria+Hallelujah&family=Lato&display=swap" rel="stylesheet">
500
  <style>
501
  body { margin: 0; padding: 20px; background: #f0f0f0; font-family: 'Lato', sans-serif; }
502
  .comic-container { max-width: 1200px; margin: 0 auto; }
@@ -509,27 +509,83 @@ class EnhancedComicGenerator:
509
  .panel img { width: 100%; height: 100%; object-fit: cover; object-position: center; transition: transform 0.1s ease-out; }
510
  .panel img.pannable { cursor: grab; }
511
  .panel img.panning { cursor: grabbing; }
512
- .speech-bubble { font-family: 'Comic Neue', cursive; position: absolute; display: flex; justify-content: center; align-items: center; width: 150px; height: 80px; min-width: 50px; min-height: 30px; box-sizing: border-box; padding: 8px; box-shadow: 2px 2px 5px rgba(0,0,0,0.3); z-index: 10; cursor: move; overflow: visible; font-size: 13px; font-weight: bold; text-align: center; }
513
  .bubble-text { padding: 2px; word-wrap: break-word; }
514
  .speech-bubble.selected { outline: 2px dashed #4CAF50; }
515
  .speech-bubble textarea { position: absolute; top: 0; left: 0; width: 100%; height: 100%; box-sizing: border-box; border: 1px solid #4CAF50; background: rgba(255,255,255,0.95); font: inherit; text-align: center; resize: none; padding: 8px; z-index: 102; }
516
- .speech-bubble.speech { background: white; border: 2px solid #333; color: #333; border-radius: 15px; }
517
- .speech-bubble.thought { background: white; border: 2px dashed #555; color: #333; border-radius: 50%; }
518
- .speech-bubble.reaction { background: #FFD700; border: 3px solid #E53935; color: #D32F2F; font-weight: 900; text-transform: uppercase; width: 180px; clip-path: polygon(0% 25%, 17% 21%, 17% 0%, 31% 16%, 50% 4%, 69% 16%, 83% 0%, 83% 21%, 100% 25%, 85% 45%, 95% 62%, 82% 79%, 100% 97%, 79% 89%, 60% 98%, 46% 82%, 27% 95%, 15% 78%, 5% 62%, 15% 45%); }
519
- .speech-bubble.narration { background: #FAFAFA; border: 2px solid #BDBDBD; color: #424242; border-radius: 3px; clip-path: polygon(0% 0%, 100% 0%, 100% 75%, 80% 75%, 70% 100%, 60% 75%, 0% 75%); }
520
- .speech-bubble.idea { background: linear-gradient(180deg,#FFFDD0 0%, #FFF8B5 100%); border: 2px solid #FFA500; color: #6a4b00; border-radius: 40% 60% 40% 60% / 60% 40% 60% 40%; clip-path: polygon(20% 0%, 80% 0%, 100% 50%, 80% 100%, 20% 100%, 0% 50%); }
521
- .speech-bubble.speech::after, .speech-bubble.idea::after { content: ''; position: absolute; width: 0; height: 0; border-left: 10px solid transparent; border-right: 10px solid transparent; }
522
- .speech-bubble.speech::after { border-top: 10px solid #333; bottom: -9px; left: 20px; }
523
- .speech-bubble.thought::after { display: none; }
524
- .thought-dot { position: absolute; background-color: white; border: 2px solid #555; border-radius: 50%; z-index: -1; }
525
- .thought-dot-1 { width: 20px; height: 20px; bottom: -20px; left: 15px; }
526
- .thought-dot-2 { width: 12px; height: 12px; bottom: -32px; left: 5px; }
527
- .speech-bubble.flipped.speech::after, .speech-bubble.flipped.idea::after { left: auto; right: 20px; }
528
- .speech-bubble.flipped.thought .thought-dot-1 { left: auto; right: 15px; }
529
- .speech-bubble.flipped.thought .thought-dot-2 { left: auto; right: 5px; }
530
- .speech-bubble.flipped-vertical.speech::after, .speech-bubble.flipped-vertical.idea::after { bottom: auto; top: -9px; transform: rotate(180deg); }
531
- .speech-bubble.flipped-vertical.thought .thought-dot-1 { bottom: auto; top: -20px; }
532
- .speech-bubble.flipped-vertical.thought .thought-dot-2 { bottom: auto; top: -32px; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
533
  .resize-handle { position: absolute; width: 10px; height: 10px; background: #2196F3; border: 1px solid white; border-radius: 50%; display: none; z-index: 11; }
534
  .speech-bubble.selected .resize-handle { display: block; }
535
  .resize-handle.se { bottom: -5px; right: -5px; cursor: se-resize; }
@@ -567,6 +623,7 @@ class EnhancedComicGenerator:
567
  <option value="speech">Speech</option><option value="thought">Thought</option><option value="reaction">Reaction</option><option value="narration">Narration</option><option value="idea">Idea</option>
568
  </select>
569
  <select id="font-select" onchange="changeFont(this.value)" disabled>
 
570
  <option value="'Comic Neue', cursive">Comic Neue</option>
571
  <option value="'Bangers', cursive">Bangers</option>
572
  <option value="'Gloria Hallelujah', cursive">Gloria</option>
@@ -582,7 +639,7 @@ class EnhancedComicGenerator:
582
  <input type="color" id="bubble-fill-color" value="#FFFFFF" disabled>
583
  </div>
584
  </div>
585
- <button onclick="rotateBubbleTail()" class="secondary-button">🔄 Rotate Tail</button>
586
  <button onclick="addBubbleToPanel()" class="action-button">💬 Add Bubble</button>
587
  <button onclick="deleteBubble()" class="reset-button">🗑️ Delete Bubble</button>
588
  </div>
@@ -717,21 +774,12 @@ class EnhancedComicGenerator:
717
  }
718
 
719
  function applyBubbleType(bubble, type) {
720
- bubble.querySelectorAll('.thought-dot').forEach(el => el.remove());
721
- let classesToKeep = 'speech-bubble';
722
- if (bubble.classList.contains('selected')) classesToKeep += ' selected';
723
- if (bubble.classList.contains('flipped')) classesToKeep += ' flipped';
724
- if (bubble.classList.contains('flipped-vertical')) classesToKeep += ' flipped-vertical';
725
- bubble.className = classesToKeep;
726
  bubble.classList.add(type);
727
  bubble.dataset.type = type;
728
- if (type === 'thought') {
729
- for (let i = 1; i <= 2; i++) {
730
- const dot = document.createElement('div');
731
- dot.className = `thought-dot thought-dot-${i}`;
732
- bubble.appendChild(dot);
733
- }
734
- }
735
  }
736
 
737
  function changeBubbleType(type) {
@@ -746,12 +794,7 @@ class EnhancedComicGenerator:
746
 
747
  function rotateBubbleTail() {
748
  if (!currentlySelectedBubble) { alert("Please select a bubble first."); return; }
749
- const isFlippedH = currentlySelectedBubble.classList.contains('flipped');
750
- const isFlippedV = currentlySelectedBubble.classList.contains('flipped-vertical');
751
- if (!isFlippedH && !isFlippedV) { currentlySelectedBubble.classList.add('flipped'); }
752
- else if (isFlippedH && !isFlippedV) { currentlySelectedBubble.classList.add('flipped-vertical'); }
753
- else if (isFlippedH && isFlippedV) { currentlySelectedBubble.classList.remove('flipped'); }
754
- else { currentlySelectedBubble.classList.remove('flipped-vertical'); }
755
  }
756
 
757
  function selectPanel(panel) {
 
496
  <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
497
  <link rel="preconnect" href="https://fonts.googleapis.com">
498
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
499
+ <link href="https://fonts.googleapis.com/css2?family=Bangers&family=Comic+Neue:wght@700&family=Gloria+Hallelujah&family=Lato&family=Permanent+Marker&display=swap" rel="stylesheet">
500
  <style>
501
  body { margin: 0; padding: 20px; background: #f0f0f0; font-family: 'Lato', sans-serif; }
502
  .comic-container { max-width: 1200px; margin: 0 auto; }
 
509
  .panel img { width: 100%; height: 100%; object-fit: cover; object-position: center; transition: transform 0.1s ease-out; }
510
  .panel img.pannable { cursor: grab; }
511
  .panel img.panning { cursor: grabbing; }
512
+ .speech-bubble { position: absolute; display: flex; justify-content: center; align-items: center; width: 150px; height: 80px; min-width: 50px; min-height: 30px; box-sizing: border-box; padding: 8px; box-shadow: 2px 2px 5px rgba(0,0,0,0.3); z-index: 10; cursor: move; overflow: visible; font-size: 13px; font-weight: bold; text-align: center; }
513
  .bubble-text { padding: 2px; word-wrap: break-word; }
514
  .speech-bubble.selected { outline: 2px dashed #4CAF50; }
515
  .speech-bubble textarea { position: absolute; top: 0; left: 0; width: 100%; height: 100%; box-sizing: border-box; border: 1px solid #4CAF50; background: rgba(255,255,255,0.95); font: inherit; text-align: center; resize: none; padding: 8px; z-index: 102; }
516
+
517
+ /* --- NEW BUBBLE STYLES --- */
518
+ .speech-bubble.speech {
519
+ padding: 20px 30px;
520
+ border-radius: 10px;
521
+ border: 3px solid black;
522
+ background: white;
523
+ color: black;
524
+ font-family: "Permanent Marker", cursive;
525
+ }
526
+ .speech-bubble.speech:before {
527
+ content: '';
528
+ position: absolute;
529
+ bottom: -50px;
530
+ height: 50px;
531
+ width: 90px;
532
+ border-radius: 0 0 100%;
533
+ box-shadow: -2px -2px 0 0 #000 inset, -23px 0 0 0 #fff inset, -25px -2px 0 0 #000 inset;
534
+ left: 0;
535
+ }
536
+ .speech-bubble.speech.flipped:before {
537
+ border-radius: 0 0 0 100%;
538
+ box-shadow: 2px -2px 0 0 #000 inset, 23px 0 0 0 #fff inset, 25px -2px 0 0 #000 inset;
539
+ right: 0;
540
+ left: auto;
541
+ }
542
+
543
+ .speech-bubble.thought {
544
+ border-radius: 50%;
545
+ border: 3px solid black;
546
+ background: white;
547
+ color: black;
548
+ }
549
+ .speech-bubble.thought:before {
550
+ content: '';
551
+ position: absolute;
552
+ height: 3px;
553
+ width: 3px;
554
+ bottom: -20px;
555
+ border-radius: 100%;
556
+ background: #fff;
557
+ left: 20px;
558
+ box-shadow: 0 0 0 7px white, 0 0 0 10px black, -20px 15px 0 5px white, -20px 15px 0 8px black, -40px 20px 0 2px white, -40px 20px 0 5px black;
559
+ }
560
+ .speech-bubble.thought.flipped:before {
561
+ right: 20px;
562
+ left: auto;
563
+ box-shadow: 0 0 0 7px white, 0 0 0 10px black, 20px 15px 0 5px white, 20px 15px 0 8px black, 40px 20px 0 2px white, 40px 20px 0 5px black;
564
+ }
565
+
566
+ .speech-bubble.reaction {
567
+ background: #FFD700;
568
+ border: 3px solid #E53935;
569
+ color: #D32F2F;
570
+ font-weight: 900;
571
+ border-radius: 50%;
572
+ position: relative;
573
+ }
574
+ .speech-bubble.reaction:before, .speech-bubble.reaction:after {
575
+ content: '';
576
+ position: absolute;
577
+ top: -3px; left: -3px; right: -3px; bottom: -3px;
578
+ background: inherit;
579
+ clip-path: polygon(50% 0%, 60% 40%, 100% 40%, 70% 65%, 85% 100%, 50% 75%, 15% 100%, 30% 65%, 0% 40%, 40% 40%);
580
+ z-index: -1;
581
+ }
582
+ .speech-bubble.reaction:after {
583
+ transform: rotate(20deg);
584
+ }
585
+
586
+ .speech-bubble.narration { background: #FAFAFA; border: 2px solid #BDBDBD; color: #424242; border-radius: 3px; }
587
+ .speech-bubble.idea { background: linear-gradient(180deg,#FFFDD0 0%, #FFF8B5 100%); border: 2px solid #FFA500; color: #6a4b00; border-radius: 40% 60% 40% 60% / 60% 40% 60% 40%; }
588
+
589
  .resize-handle { position: absolute; width: 10px; height: 10px; background: #2196F3; border: 1px solid white; border-radius: 50%; display: none; z-index: 11; }
590
  .speech-bubble.selected .resize-handle { display: block; }
591
  .resize-handle.se { bottom: -5px; right: -5px; cursor: se-resize; }
 
623
  <option value="speech">Speech</option><option value="thought">Thought</option><option value="reaction">Reaction</option><option value="narration">Narration</option><option value="idea">Idea</option>
624
  </select>
625
  <select id="font-select" onchange="changeFont(this.value)" disabled>
626
+ <option value="'Permanent Marker', cursive">Permanent Marker</option>
627
  <option value="'Comic Neue', cursive">Comic Neue</option>
628
  <option value="'Bangers', cursive">Bangers</option>
629
  <option value="'Gloria Hallelujah', cursive">Gloria</option>
 
639
  <input type="color" id="bubble-fill-color" value="#FFFFFF" disabled>
640
  </div>
641
  </div>
642
+ <button onclick="rotateBubbleTail()" class="secondary-button">🔄 Flip Tail</button>
643
  <button onclick="addBubbleToPanel()" class="action-button">💬 Add Bubble</button>
644
  <button onclick="deleteBubble()" class="reset-button">🗑️ Delete Bubble</button>
645
  </div>
 
774
  }
775
 
776
  function applyBubbleType(bubble, type) {
777
+ let classesToKeep = ['speech-bubble'];
778
+ if (bubble.classList.contains('selected')) classesToKeep.push('selected');
779
+ if (bubble.classList.contains('flipped')) classesToKeep.push('flipped');
780
+ bubble.className = classesToKeep.join(' ');
 
 
781
  bubble.classList.add(type);
782
  bubble.dataset.type = type;
 
 
 
 
 
 
 
783
  }
784
 
785
  function changeBubbleType(type) {
 
794
 
795
  function rotateBubbleTail() {
796
  if (!currentlySelectedBubble) { alert("Please select a bubble first."); return; }
797
+ currentlySelectedBubble.classList.toggle('flipped');
 
 
 
 
 
798
  }
799
 
800
  function selectPanel(panel) {