circulartext commited on
Commit
4fd8be6
·
verified ·
1 Parent(s): 81e52c9

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +179 -136
app.py CHANGED
@@ -25,11 +25,11 @@ SPECIAL_WORDS = [
25
  ]
26
 
27
  # Global variables
28
- original_word_styles = {}
29
  selected_words = []
30
 
31
- def generate_word_design(word, word_id):
32
- """Generate initial styled design for a word (black color)."""
33
  fonts = [
34
  "'VT323', monospace",
35
  "'Josefin Sans', sans-serif",
@@ -47,75 +47,154 @@ def generate_word_design(word, word_id):
47
  "'Pacifico', cursive",
48
  "'Teko', sans-serif"
49
  ]
50
- font_sizes = ["18px", "19px", "20px"]
51
- font_tops = ["0px", "1px", "-1px"]
52
- letter_spacings = ["-1px", "0px", "1px", "2px"]
53
- text_shadows = [
54
- "0px 0px 1px #000",
55
- "0px 0px 2px #000",
56
- "1px 0px 0px #000",
57
- "0px 0px 0px #000",
58
- "0px 1px 0px #000",
59
- "0px 2px 0px #000",
60
- "0px 1px 1px #000",
61
- "1px 1px 0px #000",
62
- "1px 0px 1px #000"
63
- ]
64
- skew_angles = ["-25deg", "-20deg", "-15deg", "-10deg", "0deg", "10deg", "15deg", "20deg", "25deg"]
 
 
65
 
66
  letters = list(word)
67
  styled_letters = []
68
- letter_styles_data = []
69
 
70
- for i, letter in enumerate(letters):
71
- # Generate and store original styles
72
- font_family = random.choice(fonts)
73
- font_size = random.choice(font_sizes)
74
- letter_spacing = random.choice(letter_spacings)
75
- text_shadow = random.choice(text_shadows)
76
- skew_angle = random.choice(skew_angles)
77
- margin_top = random.choice(["-0.02cm", "0.00cm", "0.02cm"])
78
- top = random.choice(font_tops)
79
-
80
- # Store original styles for transition
81
- letter_styles_data.append({
82
- 'font_family': font_family,
83
- 'font_size': font_size,
84
- 'letter_spacing': letter_spacing,
85
- 'text_shadow': text_shadow,
86
- 'skew_angle': skew_angle,
87
- 'margin_top': margin_top,
88
- 'top': top
89
- })
90
-
91
- style = {
92
- 'font-family': font_family,
93
- 'line-height': '1.6',
94
- 'font-size': font_size,
95
- 'letter-spacing': letter_spacing,
96
- 'text-shadow': text_shadow,
97
- 'transform': f'skew({skew_angle})',
98
- 'margin-top': margin_top,
99
- 'position': 'relative',
100
- 'top': top,
101
- 'color': '#000000',
102
- 'display': 'inline-block',
103
- 'margin': '0 1px',
104
- 'vertical-align': 'middle',
105
- 'transition': 'all 0.8s ease-in-out' # Smooth transition for all properties
106
- }
107
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
  style_str = '; '.join([f'{k}: {v}' for k, v in style.items()])
109
  styled_letter = f'<span class="letter-{word_id}-{i}" style="{style_str}">{letter}</span>'
110
  styled_letters.append(styled_letter)
111
 
112
- # Store styles for animation
113
- original_word_styles[word_id] = {
114
- 'word': word,
115
- 'letter_styles': letter_styles_data
116
- }
117
-
118
  return f'''
 
119
  <span class="word-container" id="word-{word_id}" style="display: inline-block;
120
  margin: 10px;
121
  padding: 8px 12px;
@@ -131,15 +210,15 @@ def generate_word_design(word, word_id):
131
 
132
  def generate_random_words():
133
  """Generate 5 random words with initial styling."""
134
- global original_word_styles, selected_words
135
 
136
  # Reset data
137
- original_word_styles = {}
138
  selected_words = random.sample(SPECIAL_WORDS, 5)
139
 
140
  styled_words = []
141
  for i, word in enumerate(selected_words):
142
- word_design = generate_word_design(word, i)
143
  styled_words.append(word_design)
144
 
145
  final_output = f"""
@@ -185,90 +264,54 @@ def generate_random_words():
185
  return final_output
186
 
187
  def trigger_movement(input_html):
188
- """Function to create smooth transitions from original values to new values."""
189
- global original_word_styles, selected_words
190
 
191
- if not original_word_styles or not selected_words:
192
  return input_html
193
 
194
- # Generate new target styles for transition
195
- fonts = [
196
- "'VT323', monospace", "'Josefin Sans', sans-serif", "'Rajdhani', sans-serif", "'Anton', sans-serif",
197
- "'Caveat', cursive", "'Patrick Hand', cursive", "'Nothing You Could Do', cursive", "'Reenie Beanie', cursive",
198
- "'Orbitron', sans-serif", "'Raleway', sans-serif", "'Open Sans Condensed', sans-serif", "'Poiret One', cursive",
199
- "'Indie Flower', cursive", "'Pacifico', cursive", "'Teko', sans-serif"
200
- ]
201
 
202
- # Create JavaScript for smooth transitions
203
- animation_script = """
204
- <script>
205
- function triggerSmoothTransitions() {
206
- """
207
-
208
- for word_id, data in original_word_styles.items():
209
- word = data['word']
210
- letter_styles = data['letter_styles']
211
-
212
- for i, original_style in enumerate(letter_styles):
213
- # Generate NEW target values
214
- new_color = f"#{random.randint(0, 0xFFFFFF):06x}"
215
- new_font_family = random.choice(fonts)
216
- new_font_size = random.choice(["20px", "22px", "24px", "26px"])
217
- new_letter_spacing = random.choice(["-3px", "-2px", "0px", "2px", "3px", "4px"])
218
- new_text_shadow = random.choice([
219
- f"0px 0px 5px {new_color}",
220
- f"2px 2px 4px {new_color}",
221
- f"0px 0px 8px {new_color}",
222
- f"3px 3px 6px {new_color}",
223
- "none"
224
- ])
225
- new_skew = random.choice(["-35deg", "-25deg", "0deg", "25deg", "35deg", "45deg"])
226
- new_top = random.choice(["-3px", "0px", "3px", "5px"])
227
- new_margin_top = random.choice(["-0.05cm", "0.00cm", "0.03cm", "0.05cm"])
228
 
229
- animation_script += f"""
230
- // Animate letter {i} of word {word_id}
231
- setTimeout(() => {{
232
- const letter = document.querySelector('.letter-{word_id}-{i}');
233
- if (letter) {{
234
- // Font changes instantly (can't interpolate)
235
- letter.style.fontFamily = '{new_font_family}';
236
 
237
- // These properties transition smoothly from original to new values
238
- letter.style.color = '{new_color}';
239
- letter.style.fontSize = '{new_font_size}';
240
- letter.style.letterSpacing = '{new_letter_spacing}';
241
- letter.style.textShadow = '{new_text_shadow}';
242
- letter.style.transform = 'skew({new_skew}) scale(1.1)';
243
- letter.style.top = '{new_top}';
244
- letter.style.marginTop = '{new_margin_top}';
245
- }}
246
- }}, {i * 100});
247
- """
248
-
249
- animation_script += """
250
- }
251
-
252
- // Trigger the transitions
253
- triggerSmoothTransitions();
254
- </script>
255
- """
256
-
257
- # Add the script to the HTML
258
- if "</body>" in input_html:
259
- updated_html = input_html.replace("</body>", animation_script + "</body>")
260
- else:
261
- updated_html = input_html + animation_script
262
-
263
  return updated_html
264
 
265
  # Create Gradio interface using Blocks
266
  with gr.Blocks() as demo:
267
- gr.Markdown("# Random Word Styler\nWords smoothly transition from their original styling to completely new styling!")
268
 
269
  generate_button = gr.Button("Generate Random Words", variant="primary")
270
  output_html = gr.HTML()
271
- animate_button = gr.Button("Trigger Smooth Movement", variant="secondary")
272
 
273
  generate_button.click(generate_random_words, outputs=output_html)
274
  animate_button.click(trigger_movement, inputs=output_html, outputs=output_html)
 
25
  ]
26
 
27
  # Global variables
28
+ original_designs = {}
29
  selected_words = []
30
 
31
+ def generate_word_design(word, word_id, is_animated=False):
32
+ """Generate styled design for a word."""
33
  fonts = [
34
  "'VT323', monospace",
35
  "'Josefin Sans', sans-serif",
 
47
  "'Pacifico', cursive",
48
  "'Teko', sans-serif"
49
  ]
50
+
51
+ if not is_animated:
52
+ # Original state values
53
+ font_sizes = ["18px", "19px", "20px"]
54
+ font_tops = ["0px", "1px", "-1px"]
55
+ letter_spacings = ["-1px", "0px", "1px", "2px"]
56
+ text_shadows = ["0px 0px 1px #000", "0px 0px 2px #000", "1px 0px 0px #000", "0px 0px 0px #000"]
57
+ skew_angles = ["-25deg", "-20deg", "-15deg", "-10deg", "0deg", "10deg", "15deg", "20deg", "25deg"]
58
+ colors = ["#000000"]
59
+ else:
60
+ # Animated state values
61
+ font_sizes = ["20px", "22px", "24px", "26px"]
62
+ font_tops = ["-3px", "0px", "3px", "5px"]
63
+ letter_spacings = ["-3px", "-2px", "0px", "2px", "3px", "4px"]
64
+ text_shadows = ["0px 0px 5px", "2px 2px 4px", "0px 0px 8px", "3px 3px 6px", "1px 1px 10px"]
65
+ skew_angles = ["-35deg", "-25deg", "0deg", "25deg", "35deg", "45deg"]
66
+ colors = [f"#{random.randint(0, 0xFFFFFF):06x}" for _ in range(10)]
67
 
68
  letters = list(word)
69
  styled_letters = []
70
+ keyframes_css = ""
71
 
72
+ if is_animated:
73
+ # Get original styles to create transition keyframes
74
+ original_data = original_designs.get(word_id, {})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
 
76
+ for i, letter in enumerate(letters):
77
+ if not is_animated:
78
+ # Store original values for later animation
79
+ if word_id not in original_designs:
80
+ original_designs[word_id] = {'letters': []}
81
+
82
+ original_styles = {
83
+ 'font_family': random.choice(fonts),
84
+ 'font_size': random.choice(font_sizes),
85
+ 'letter_spacing': random.choice(letter_spacings),
86
+ 'text_shadow': random.choice(text_shadows),
87
+ 'skew_angle': random.choice(skew_angles),
88
+ 'margin_top': random.choice(["-0.02cm", "0.00cm", "0.02cm"]),
89
+ 'top': random.choice(font_tops),
90
+ 'color': '#000000'
91
+ }
92
+ original_designs[word_id]['letters'].append(original_styles)
93
+
94
+ style = {
95
+ 'font-family': original_styles['font_family'],
96
+ 'line-height': '1.6',
97
+ 'font-size': original_styles['font_size'],
98
+ 'letter-spacing': original_styles['letter_spacing'],
99
+ 'text-shadow': original_styles['text_shadow'],
100
+ 'transform': f'skew({original_styles["skew_angle"]})',
101
+ 'margin-top': original_styles['margin_top'],
102
+ 'position': 'relative',
103
+ 'top': original_styles['top'],
104
+ 'color': original_styles['color'],
105
+ 'display': 'inline-block',
106
+ 'margin': '0 1px',
107
+ 'vertical-align': 'middle'
108
+ }
109
+ else:
110
+ # Create animated version with keyframes
111
+ original_letter_styles = original_data['letters'][i] if i < len(original_data.get('letters', [])) else {}
112
+
113
+ # New target values
114
+ new_font_family = random.choice(fonts)
115
+ new_font_size = random.choice(font_sizes)
116
+ new_letter_spacing = random.choice(letter_spacings)
117
+ new_color = random.choice(colors)
118
+ new_text_shadow = f"{random.choice(text_shadows)} {new_color}"
119
+ new_skew_angle = random.choice(skew_angles)
120
+ new_top = random.choice(font_tops)
121
+ new_margin_top = random.choice(["-0.05cm", "0.00cm", "0.03cm", "0.05cm"])
122
+
123
+ # Create unique animation name
124
+ animation_name = f"move_{word_id}_{i}_{random.randint(1000, 9999)}"
125
+
126
+ # Get original values for keyframes
127
+ orig_font_size = original_letter_styles.get('font_size', '18px')
128
+ orig_letter_spacing = original_letter_styles.get('letter_spacing', '0px')
129
+ orig_color = original_letter_styles.get('color', '#000000')
130
+ orig_text_shadow = original_letter_styles.get('text_shadow', '0px 0px 0px #000')
131
+ orig_skew_angle = original_letter_styles.get('skew_angle', '0deg')
132
+ orig_top = original_letter_styles.get('top', '0px')
133
+ orig_margin_top = original_letter_styles.get('margin_top', '0.00cm')
134
+
135
+ # Create keyframes that transition from original to new values
136
+ keyframes_css += f"""
137
+ @keyframes {animation_name} {{
138
+ 0% {{
139
+ font-size: {orig_font_size};
140
+ letter-spacing: {orig_letter_spacing};
141
+ color: {orig_color};
142
+ text-shadow: {orig_text_shadow};
143
+ transform: skew({orig_skew_angle}) scale(1);
144
+ top: {orig_top};
145
+ margin-top: {orig_margin_top};
146
+ }}
147
+ 25% {{
148
+ font-size: {new_font_size};
149
+ letter-spacing: {new_letter_spacing};
150
+ color: {new_color};
151
+ text-shadow: {new_text_shadow};
152
+ transform: skew({new_skew_angle}) scale(1.2);
153
+ top: {new_top};
154
+ margin-top: {new_margin_top};
155
+ }}
156
+ 50% {{
157
+ transform: skew({new_skew_angle}) scale(0.9);
158
+ }}
159
+ 75% {{
160
+ transform: skew({new_skew_angle}) scale(1.1);
161
+ }}
162
+ 100% {{
163
+ font-size: {new_font_size};
164
+ letter-spacing: {new_letter_spacing};
165
+ color: {new_color};
166
+ text-shadow: {new_text_shadow};
167
+ transform: skew({new_skew_angle}) scale(1);
168
+ top: {new_top};
169
+ margin-top: {new_margin_top};
170
+ }}
171
+ }}
172
+ """
173
+
174
+ style = {
175
+ 'font-family': new_font_family, # Font changes instantly
176
+ 'line-height': '1.6',
177
+ 'font-size': new_font_size,
178
+ 'letter-spacing': new_letter_spacing,
179
+ 'text-shadow': new_text_shadow,
180
+ 'transform': f'skew({new_skew_angle})',
181
+ 'margin-top': new_margin_top,
182
+ 'position': 'relative',
183
+ 'top': new_top,
184
+ 'color': new_color,
185
+ 'display': 'inline-block',
186
+ 'margin': '0 1px',
187
+ 'vertical-align': 'middle',
188
+ 'animation': f'{animation_name} 1.5s ease-in-out forwards',
189
+ 'animation-delay': f'{i * 0.1}s'
190
+ }
191
+
192
  style_str = '; '.join([f'{k}: {v}' for k, v in style.items()])
193
  styled_letter = f'<span class="letter-{word_id}-{i}" style="{style_str}">{letter}</span>'
194
  styled_letters.append(styled_letter)
195
 
 
 
 
 
 
 
196
  return f'''
197
+ {f"<style>{keyframes_css}</style>" if keyframes_css else ""}
198
  <span class="word-container" id="word-{word_id}" style="display: inline-block;
199
  margin: 10px;
200
  padding: 8px 12px;
 
210
 
211
  def generate_random_words():
212
  """Generate 5 random words with initial styling."""
213
+ global original_designs, selected_words
214
 
215
  # Reset data
216
+ original_designs = {}
217
  selected_words = random.sample(SPECIAL_WORDS, 5)
218
 
219
  styled_words = []
220
  for i, word in enumerate(selected_words):
221
+ word_design = generate_word_design(word, i, is_animated=False)
222
  styled_words.append(word_design)
223
 
224
  final_output = f"""
 
264
  return final_output
265
 
266
  def trigger_movement(input_html):
267
+ """Replace words with animated versions that transition from original to new styling."""
268
+ global original_designs, selected_words
269
 
270
+ if not original_designs or not selected_words:
271
  return input_html
272
 
273
+ updated_html = input_html
 
 
 
 
 
 
274
 
275
+ # Replace each word with its animated version
276
+ for i, word in enumerate(selected_words):
277
+ if i in original_designs:
278
+ # Generate animated version that transitions from original values
279
+ animated_design = generate_word_design(word, i, is_animated=True)
280
+
281
+ # Find and replace the original word container
282
+ old_pattern = f'<span class="word-container" id="word-{i}"'
283
+ old_end = '</span></span>'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
284
 
285
+ # Find the full original word HTML
286
+ start_idx = updated_html.find(old_pattern)
287
+ if start_idx != -1:
288
+ # Find the end of this word container
289
+ temp_html = updated_html[start_idx:]
290
+ span_count = 0
291
+ end_idx = start_idx
292
 
293
+ for j, char in enumerate(temp_html):
294
+ if temp_html[j:j+5] == '<span':
295
+ span_count += 1
296
+ elif temp_html[j:j+7] == '</span>':
297
+ span_count -= 1
298
+ if span_count == 0:
299
+ end_idx = start_idx + j + 7
300
+ break
301
+
302
+ if end_idx > start_idx:
303
+ old_word_html = updated_html[start_idx:end_idx]
304
+ updated_html = updated_html.replace(old_word_html, animated_design, 1)
305
+
 
 
 
 
 
 
 
 
 
 
 
 
 
306
  return updated_html
307
 
308
  # Create Gradio interface using Blocks
309
  with gr.Blocks() as demo:
310
+ gr.Markdown("# Random Word Styler\nWords progressively transition from original styling to new styling!")
311
 
312
  generate_button = gr.Button("Generate Random Words", variant="primary")
313
  output_html = gr.HTML()
314
+ animate_button = gr.Button("Trigger Progressive Movement", variant="secondary")
315
 
316
  generate_button.click(generate_random_words, outputs=output_html)
317
  animate_button.click(trigger_movement, inputs=output_html, outputs=output_html)