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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +130 -95
app.py CHANGED
@@ -25,11 +25,11 @@ SPECIAL_WORDS = [
25
  ]
26
 
27
  # Global variables
28
- original_word_designs = {}
29
  selected_words = []
30
 
31
- def generate_word_design(word, word_id, use_color=False):
32
- """Generate styled design for a word."""
33
  fonts = [
34
  "'VT323', monospace",
35
  "'Josefin Sans', sans-serif",
@@ -47,94 +47,75 @@ def generate_word_design(word, word_id, use_color=False):
47
  "'Pacifico', cursive",
48
  "'Teko', sans-serif"
49
  ]
50
- font_sizes = ["18px", "19px", "20px"] if not use_color else ["20px", "22px", "24px"]
51
- font_tops = ["0px", "1px", "-1px"] if not use_color else ["-2px", "0px", "2px", "3px"]
52
- letter_spacings = ["-1px", "0px", "1px"] if not use_color else ["-2px", "0px", "2px", "3px"]
53
  text_shadows = [
54
- "0px 0px 1px",
55
- "0px 0px 2px",
56
- "1px 0px 0px",
57
- "0px 0px 0px",
58
- "0px 1px 0px",
59
- "0px 2px 0px",
60
- "0px 1px 1px",
61
- "1px 1px 0px",
62
- "1px 0px 1px"
63
- ] if not use_color else [
64
- "0px 0px 5px",
65
- "2px 2px 4px",
66
- "0px 0px 8px",
67
- "3px 3px 6px",
68
- "1px 1px 10px"
69
  ]
70
- skew_angles = ["-25deg", "-20deg", "-15deg", "-10deg", "0deg", "10deg", "15deg", "20deg", "25deg"] if not use_color else ["-35deg", "-25deg", "0deg", "25deg", "35deg", "40deg"]
71
-
72
- # Choose color
73
- color = '#000000' if not use_color else f'#{random.randint(0, 0xFFFFFF):06x}'
74
-
75
- # Generate unique animation name for movement
76
- animation_name = f"animate_{word_id}_{random.randint(0, 10000)}"
77
 
78
  letters = list(word)
79
  styled_letters = []
 
80
 
81
  for i, letter in enumerate(letters):
82
- # Generate COMPLETELY NEW random styles (not based on original)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
  style = {
84
- 'font-family': random.choice(fonts),
85
  'line-height': '1.6',
86
- 'font-size': random.choice(font_sizes),
87
- 'letter-spacing': random.choice(letter_spacings),
88
- 'text-shadow': random.choice(text_shadows),
89
- 'transform': f'skew({random.choice(skew_angles)})',
90
- 'margin-top': random.choice(["-0.03cm", "-0.01cm", "0.00cm", "0.01cm", "0.03cm"]),
91
  'position': 'relative',
92
- 'top': random.choice(font_tops),
93
- 'color': color,
94
  'display': 'inline-block',
95
  'margin': '0 1px',
96
- 'vertical-align': 'middle'
 
97
  }
98
 
99
- if use_color:
100
- # Animation plays once and stops (no infinite)
101
- style['animation'] = f'{animation_name} 1.2s ease-in-out forwards'
102
- style['animation-delay'] = f'{i * 0.15}s'
103
-
104
  style_str = '; '.join([f'{k}: {v}' for k, v in style.items()])
105
- styled_letter = f'<span class="styled-letter" style="{style_str}">{letter}</span>'
106
  styled_letters.append(styled_letter)
107
 
108
- # Create keyframes for movement animation - plays once and stops
109
- keyframes = f"""
110
- <style>
111
- @keyframes {animation_name} {{
112
- 0% {{
113
- transform: scale(1) rotate(0deg) skew({random.choice(skew_angles)});
114
- opacity: 0.7;
115
- }}
116
- 25% {{
117
- transform: scale(1.3) rotate({random.choice(["-15deg", "15deg", "20deg"])}deg) skew({random.choice(skew_angles)});
118
- opacity: 1;
119
- }}
120
- 50% {{
121
- transform: scale(0.9) rotate({random.choice(["-10deg", "10deg", "25deg"])}deg) skew({random.choice(skew_angles)});
122
- opacity: 1;
123
- }}
124
- 75% {{
125
- transform: scale(1.2) rotate({random.choice(["-5deg", "5deg", "30deg"])}deg) skew({random.choice(skew_angles)});
126
- opacity: 1;
127
- }}
128
- 100% {{
129
- transform: scale(1.1) rotate(0deg) skew({random.choice(skew_angles)});
130
- opacity: 1;
131
- }}
132
- }}
133
- </style>
134
- """ if use_color else ""
135
 
136
  return f'''
137
- {keyframes}
138
  <span class="word-container" id="word-{word_id}" style="display: inline-block;
139
  margin: 10px;
140
  padding: 8px 12px;
@@ -150,18 +131,16 @@ def generate_word_design(word, word_id, use_color=False):
150
 
151
  def generate_random_words():
152
  """Generate 5 random words with initial styling."""
153
- global original_word_designs, selected_words
154
 
155
  # Reset data
156
- original_word_designs = {}
157
  selected_words = random.sample(SPECIAL_WORDS, 5)
158
 
159
  styled_words = []
160
  for i, word in enumerate(selected_words):
161
- # Generate original design (black)
162
- original_design = generate_word_design(word, i, use_color=False)
163
- original_word_designs[i] = original_design
164
- styled_words.append(original_design)
165
 
166
  final_output = f"""
167
  <html>
@@ -190,9 +169,6 @@ def generate_random_words():
190
  font-family: "Josefin Sans", sans-serif;
191
  padding: 20px;
192
  }}
193
- .styled-letter {{
194
- transition: all 0.6s ease;
195
- }}
196
  </style>
197
  </head>
198
  <body>
@@ -209,31 +185,90 @@ def generate_random_words():
209
  return final_output
210
 
211
  def trigger_movement(input_html):
212
- """Function to trigger the movement by replacing each word with a completely NEW styled version."""
213
- global original_word_designs, selected_words
214
 
215
- if not original_word_designs or not selected_words:
216
  return input_html
217
 
218
- updated_html = input_html
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
219
 
220
- # Replace each word with its completely new animated version
221
- for i, word in enumerate(selected_words):
222
- if i in original_word_designs:
223
- # Generate COMPLETELY NEW design with color and animation (that stops)
224
- new_movement_design = generate_word_design(word, i, use_color=True)
225
- # Replace the original design with the new one
226
- updated_html = updated_html.replace(original_word_designs[i], new_movement_design, 1)
227
-
228
  return updated_html
229
 
230
  # Create Gradio interface using Blocks
231
  with gr.Blocks() as demo:
232
- gr.Markdown("# Random Word Styler\nGenerate 5 random styled words that transform with a one-time animation!")
233
 
234
  generate_button = gr.Button("Generate Random Words", variant="primary")
235
  output_html = gr.HTML()
236
- animate_button = gr.Button("Trigger Movement Animation", variant="secondary")
237
 
238
  generate_button.click(generate_random_words, outputs=output_html)
239
  animate_button.click(trigger_movement, inputs=output_html, outputs=output_html)
 
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
  "'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
 
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"""
146
  <html>
 
169
  font-family: "Josefin Sans", sans-serif;
170
  padding: 20px;
171
  }}
 
 
 
172
  </style>
173
  </head>
174
  <body>
 
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)