circulartext commited on
Commit
2daf147
·
verified ·
1 Parent(s): 3571ebc

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +157 -34
app.py CHANGED
@@ -1,10 +1,9 @@
1
  import gradio as gr
2
  import random
3
  import time
4
- import re
5
 
6
- # === Your original per-letter styling algorithm ===
7
  def generate_initial_design(word):
 
8
  fonts = [
9
  "'VT323', monospace",
10
  "'Josefin Sans', sans-serif",
@@ -35,8 +34,8 @@ def generate_initial_design(word):
35
 
36
  letters = list(word)
37
  styled_letters = []
38
-
39
- for letter in letters:
40
  style = {
41
  'font-family': random.choice(fonts),
42
  'line-height': '1.6',
@@ -50,56 +49,180 @@ def generate_initial_design(word):
50
  'color': '#000000',
51
  'display': 'inline-block',
52
  'margin': '0 1px',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
  'vertical-align': 'middle',
54
- 'cursor': 'pointer'
 
55
  }
 
56
  style_str = '; '.join([f'{k}: {v}' for k, v in style.items()])
57
  styled_letter = f'<span class="styled-letter" style="{style_str}">{letter}</span>'
58
  styled_letters.append(styled_letter)
59
 
60
- return f"<span>{' '.join(styled_letters)}</span>"
 
 
 
 
 
 
 
 
 
 
 
 
 
61
 
62
- # === Typing effect with your letter-by-letter styled special words ===
63
  def typing_effect():
64
  paragraphs = [
65
- "Proctor's voice quavered, Where are we, Benshiro? This can't be real. We went full speed into that...”",
66
- "Proctor, I hear you! Is that you? I'm so thankful, but where are you? I can't see you.” Benshiro's words echoed in the void."
67
  ]
68
- html_output = ""
69
 
 
 
70
  for paragraph in paragraphs:
71
  words = paragraph.split()
72
- special_word = random.choice(words)
73
- styled_words = [generate_initial_design(w) if w == special_word else w for w in words]
 
 
 
74
 
75
- for w in styled_words:
76
- html_output += w + " "
77
- yield html_output
78
- time.sleep(0.05)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
 
80
- html_output += "<br><br>"
81
- time.sleep(0.3)
 
 
82
 
83
- # === Re-randomize ALL styled letters on button click ===
84
- def animate_letters(current_html):
85
- def re_style_letters(match):
86
- letter = match.group(1)
87
- return generate_initial_design(letter) if len(letter) > 1 else letter
88
 
89
- # Replace entire special word spans by regenerating styles for each letter
90
- return re.sub(r'<span[^>]*>([^<]+)</span>', lambda m: f"<span>{''.join(generate_initial_design(m.group(1)))}</span>", current_html)
91
-
92
- # === Gradio UI ===
93
  with gr.Blocks() as demo:
94
- gr.HTML("""<link href="https://fonts.googleapis.com/css?family=VT323|Josefin+Sans|Rajdhani|Anton|Caveat|Patrick+Hand|Nothing+You+Could+Do|Reenie+Beanie|Orbitron|Raleway" rel="stylesheet">""")
95
- gr.Markdown("## 🎨 Per-Letter Styled Typing Effect with Animation Button")
96
-
97
  output_html = gr.HTML()
98
  with gr.Row():
99
  start_btn = gr.Button("▶ Start Typing")
100
  animate_btn = gr.Button("✨ Re-Randomize Styles")
 
 
 
101
 
102
- start_btn.click(typing_effect, outputs=output_html)
103
- animate_btn.click(animate_letters, inputs=output_html, outputs=output_html)
104
-
105
- demo.launch()
 
1
  import gradio as gr
2
  import random
3
  import time
 
4
 
 
5
  def generate_initial_design(word):
6
+ """Generate initial design for the special word in black color."""
7
  fonts = [
8
  "'VT323', monospace",
9
  "'Josefin Sans', sans-serif",
 
34
 
35
  letters = list(word)
36
  styled_letters = []
37
+
38
+ for i, letter in enumerate(letters):
39
  style = {
40
  'font-family': random.choice(fonts),
41
  'line-height': '1.6',
 
49
  'color': '#000000',
50
  'display': 'inline-block',
51
  'margin': '0 1px',
52
+ 'vertical-align': 'middle'
53
+ }
54
+
55
+ style_str = '; '.join([f'{k}: {v}' for k, v in style.items()])
56
+ styled_letter = f'<span class="styled-letter" style="{style_str}">{letter}</span>'
57
+ styled_letters.append(styled_letter)
58
+
59
+ return f'''
60
+ <span style="display: inline-flex;
61
+ align-items: baseline;
62
+ vertical-align: middle;
63
+ margin: 0 2px;">
64
+ {" ".join(styled_letters)}
65
+ </span>'''
66
+
67
+ def generate_movement_design(word):
68
+ """Generate a completely new random design for the movement animation."""
69
+ fonts = [
70
+ "'VT323', monospace",
71
+ "'Josefin Sans', sans-serif",
72
+ "'Rajdhani', sans-serif",
73
+ "'Anton', sans-serif",
74
+ "'Caveat', cursive",
75
+ "'Patrick Hand', cursive",
76
+ "'Nothing You Could Do', cursive",
77
+ "'Reenie Beanie', cursive",
78
+ "'Orbitron', sans-serif",
79
+ "'Raleway', sans-serif"
80
+ ]
81
+ font_sizes = ["18px", "19px", "20px"]
82
+ font_tops = ["0px", "1px", "-1px"]
83
+ letter_spacings = ["-1px", "0px", "1px"]
84
+ text_shadows = [
85
+ "0px 0px 1px",
86
+ "0px 0px 2px",
87
+ "1px 0px 0px",
88
+ "0px 0px 0px",
89
+ "0px 1px 0px",
90
+ "0px 2px 0px",
91
+ "0px 1px 1px",
92
+ "1px 1px 0px",
93
+ "1px 0px 1px"
94
+ ]
95
+ skew_angles = ["-25deg", "-20deg", "-15deg", "-10deg", "0deg", "10deg", "15deg", "20deg", "25deg"]
96
+
97
+ # Generate random color for the movement design
98
+ random_color = f'#{random.randint(0, 0xFFFFFF):06x}'
99
+
100
+ # Generate unique animation name
101
+ animation_name = f"animate_{random.randint(0, 10000)}"
102
+
103
+ # Create keyframes for the animation sequence
104
+ keyframes = f"""
105
+ @keyframes {animation_name} {{
106
+ 0% {{ transform: scale(1) rotate(0deg); }}
107
+ 50% {{ transform: scale(1.2) rotate(10deg); }}
108
+ 100% {{ transform: scale(1) rotate(0deg); }}
109
+ }}
110
+ """
111
+
112
+ letters = list(word)
113
+ styled_letters = []
114
+
115
+ for i, letter in enumerate(letters):
116
+ style = {
117
+ 'font-family': random.choice(fonts),
118
+ 'line-height': '1.6',
119
+ 'font-size': random.choice(font_sizes),
120
+ 'letter-spacing': random.choice(letter_spacings),
121
+ 'text-shadow': random.choice(text_shadows),
122
+ 'transform': f'skew({random.choice(skew_angles)})',
123
+ 'margin-top': random.choice(["-0.02cm", "0.00cm", "0.02cm"]),
124
+ 'position': 'relative',
125
+ 'top': random.choice(font_tops),
126
+ 'color': random_color,
127
+ 'display': 'inline-block',
128
+ 'margin': '0 1px',
129
  'vertical-align': 'middle',
130
+ 'animation': f'{animation_name} 0.5s ease-in-out',
131
+ 'animation-delay': f'{i * 0.1}s'
132
  }
133
+
134
  style_str = '; '.join([f'{k}: {v}' for k, v in style.items()])
135
  styled_letter = f'<span class="styled-letter" style="{style_str}">{letter}</span>'
136
  styled_letters.append(styled_letter)
137
 
138
+ return f'''
139
+ <style>
140
+ {keyframes}
141
+ .styled-letter {{
142
+ transition: all 0.3s ease;
143
+ }}
144
+ </style>
145
+ <span style="display: inline-flex;
146
+ align-items: baseline;
147
+ vertical-align: middle;
148
+ margin: 0 2px;">
149
+ {" ".join(styled_letters)}
150
+ </span>
151
+ '''
152
 
 
153
  def typing_effect():
154
  paragraphs = [
155
+ "Proctors's voice quavered, "Where are we, Benshiro? This can't be real. We went full speed into that..."",
156
+ ""Proctor, I hear you! Is that you? I'm so thankful, but where are you? I can't see you." Benshiro's words echoed in the void."
157
  ]
 
158
 
159
+ # Process paragraphs to add styling
160
+ styled_paragraphs = []
161
  for paragraph in paragraphs:
162
  words = paragraph.split()
163
+ if words: # Make sure there are words in the paragraph
164
+ special_word = random.choice(words)
165
+ styled_word = generate_initial_design(special_word)
166
+ styled_paragraph = ' '.join(word if word != special_word else styled_word for word in words)
167
+ styled_paragraphs.append(styled_paragraph)
168
 
169
+ # Create the full HTML output
170
+ output_html = '<br><br>'.join(styled_paragraphs)
171
+
172
+ final_output = f"""
173
+ <html>
174
+ <head>
175
+ <link href="https://fonts.googleapis.com/css2?family=VT323&display=swap" rel="stylesheet">
176
+ <link href="https://fonts.googleapis.com/css2?family=Josefin+Sans:wght@100&display=swap" rel="stylesheet">
177
+ <link href="https://fonts.googleapis.com/css2?family=Rajdhani:wght@300&display=swap" rel="stylesheet">
178
+ <link href="https://fonts.googleapis.com/css2?family=Anton&display=swap" rel="stylesheet">
179
+ <link href="https://fonts.googleapis.com/css2?family=Caveat&display=swap" rel="stylesheet">
180
+ <link href="https://fonts.googleapis.com/css2?family=Patrick+Hand&display=swap" rel="stylesheet">
181
+ <link href="https://fonts.googleapis.com/css2?family=Nothing+You+Could+Do&display=swap" rel="stylesheet">
182
+ <link href="https://fonts.googleapis.com/css2?family=Reenie+Beanie&display=swap" rel="stylesheet">
183
+ <link href="https://fonts.googleapis.com/css2?family=Orbitron&display=swap" rel="stylesheet">
184
+ <link href="https://fonts.googleapis.com/css?family=Raleway:500" rel="stylesheet">
185
+ <style>
186
+ body {{
187
+ background-color: #fff;
188
+ color: #000;
189
+ font-size: 18px;
190
+ line-height: 1.6;
191
+ font-family: "Josefin Sans", sans-serif;
192
+ padding: 20px;
193
+ }}
194
+ </style>
195
+ </head>
196
+ <body>
197
+ <div style='max-width: 800px; margin: auto;'>
198
+ {output_html}
199
+ </div>
200
+ </body>
201
+ </html>
202
+ """
203
+
204
+ return final_output
205
 
206
+ def trigger_movement(input_html):
207
+ """Function to trigger the movement animation."""
208
+ if not input_html:
209
+ return input_html
210
 
211
+ # Find styled words and regenerate them with movement
212
+ # This is a simple approach - in practice, you might want to track the specific words
213
+ return typing_effect() # For now, regenerate with new random styling
 
 
214
 
215
+ # Create Gradio interface using Blocks
 
 
 
216
  with gr.Blocks() as demo:
217
+ gr.Markdown("# CircularText Styler\nText with special word styling and animations.")
218
+
 
219
  output_html = gr.HTML()
220
  with gr.Row():
221
  start_btn = gr.Button("▶ Start Typing")
222
  animate_btn = gr.Button("✨ Re-Randomize Styles")
223
+
224
+ start_btn.click(typing_effect, inputs=[], outputs=output_html)
225
+ animate_btn.click(trigger_movement, inputs=output_html, outputs=output_html)
226
 
227
+ # Launch the app
228
+ demo.launch()