Update app.py
Browse files
app.py
CHANGED
@@ -25,11 +25,11 @@ SPECIAL_WORDS = [
|
|
25 |
]
|
26 |
|
27 |
# Global variables
|
28 |
-
|
29 |
selected_words = []
|
30 |
|
31 |
-
def generate_word_design(word, word_id):
|
32 |
-
"""Generate
|
33 |
fonts = [
|
34 |
"'VT323', monospace",
|
35 |
"'Josefin Sans', sans-serif",
|
@@ -47,9 +47,9 @@ 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"]
|
53 |
text_shadows = [
|
54 |
"0px 0px 1px",
|
55 |
"0px 0px 2px",
|
@@ -60,62 +60,65 @@ def generate_word_design(word, word_id):
|
|
60 |
"0px 1px 1px",
|
61 |
"1px 1px 0px",
|
62 |
"1px 0px 1px"
|
|
|
|
|
|
|
|
|
|
|
|
|
63 |
]
|
64 |
-
skew_angles = ["-25deg", "-20deg", "-15deg", "-10deg", "0deg", "10deg", "15deg", "20deg", "25deg"]
|
|
|
|
|
|
|
|
|
|
|
|
|
65 |
|
66 |
letters = list(word)
|
67 |
styled_letters = []
|
68 |
-
letter_styles = [] # Store styles for animation later
|
69 |
|
70 |
for i, letter in enumerate(letters):
|
71 |
-
# Generate random 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 style data for animation
|
81 |
-
letter_styles.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':
|
93 |
'line-height': '1.6',
|
94 |
-
'font-size':
|
95 |
-
'letter-spacing':
|
96 |
-
'text-shadow':
|
97 |
-
'transform': f'skew({
|
98 |
-
'margin-top':
|
99 |
'position': 'relative',
|
100 |
-
'top':
|
101 |
-
'color':
|
102 |
'display': 'inline-block',
|
103 |
'margin': '0 1px',
|
104 |
-
'vertical-align': 'middle'
|
105 |
-
'transition': 'all 0.5s ease' # Smooth transition
|
106 |
}
|
107 |
|
|
|
|
|
|
|
|
|
108 |
style_str = '; '.join([f'{k}: {v}' for k, v in style.items()])
|
109 |
-
styled_letter = f'<span class="letter
|
110 |
styled_letters.append(styled_letter)
|
111 |
|
112 |
-
#
|
113 |
-
|
114 |
-
|
115 |
-
|
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,16 +134,18 @@ def generate_word_design(word, word_id):
|
|
131 |
|
132 |
def generate_random_words():
|
133 |
"""Generate 5 random words with initial styling."""
|
134 |
-
global
|
135 |
|
136 |
# Reset data
|
137 |
-
|
138 |
selected_words = random.sample(SPECIAL_WORDS, 5)
|
139 |
|
140 |
styled_words = []
|
141 |
for i, word in enumerate(selected_words):
|
142 |
-
|
143 |
-
|
|
|
|
|
144 |
|
145 |
final_output = f"""
|
146 |
<html>
|
@@ -169,21 +174,15 @@ def generate_random_words():
|
|
169 |
font-family: "Josefin Sans", sans-serif;
|
170 |
padding: 20px;
|
171 |
}}
|
172 |
-
|
173 |
-
|
174 |
-
50% {{ transform: scale(1.3) rotate(15deg); }}
|
175 |
-
100% {{ transform: scale(1.1) rotate(5deg); }}
|
176 |
-
}}
|
177 |
-
@keyframes colorShift {{
|
178 |
-
0% {{ filter: hue-rotate(0deg); }}
|
179 |
-
100% {{ filter: hue-rotate(360deg); }}
|
180 |
}}
|
181 |
</style>
|
182 |
</head>
|
183 |
<body>
|
184 |
<div style='max-width: 800px; margin: auto; text-align: center;'>
|
185 |
<h2 style="margin-bottom: 30px;">Random Styled Words</h2>
|
186 |
-
<div style="display: flex; flex-wrap: wrap; justify-content: center; align-items: center;">
|
187 |
{" ".join(styled_words)}
|
188 |
</div>
|
189 |
</div>
|
@@ -194,65 +193,27 @@ def generate_random_words():
|
|
194 |
return final_output
|
195 |
|
196 |
def trigger_movement(input_html):
|
197 |
-
"""Function to trigger the movement
|
198 |
-
global
|
199 |
|
200 |
-
if not
|
201 |
return input_html
|
202 |
|
203 |
-
|
204 |
-
animation_script = """
|
205 |
-
<script>
|
206 |
-
function animateWords() {
|
207 |
-
// Define color array for random colors
|
208 |
-
const colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7', '#DDA0DD', '#98D8C8', '#F7DC6F', '#BB8FCE', '#85C1E9'];
|
209 |
-
|
210 |
-
"""
|
211 |
-
|
212 |
-
for word_id, data in original_word_data.items():
|
213 |
-
word = data['word']
|
214 |
-
letter_styles = data['letter_styles']
|
215 |
-
random_color = f"colors[Math.floor(Math.random() * colors.length)]"
|
216 |
-
|
217 |
-
for i, letter_style in enumerate(letter_styles):
|
218 |
-
# Generate new random styles for the movement
|
219 |
-
new_font_size = random.choice(["20px", "22px", "24px"])
|
220 |
-
new_skew = random.choice(["-30deg", "-20deg", "0deg", "20deg", "30deg"])
|
221 |
-
new_rotation = random.choice(["-10deg", "0deg", "10deg", "15deg"])
|
222 |
-
|
223 |
-
animation_script += f"""
|
224 |
-
// Animate letter {i} of word {word_id}
|
225 |
-
setTimeout(() => {{
|
226 |
-
const letter = document.querySelector('.letter-{word_id}-{i}');
|
227 |
-
if (letter) {{
|
228 |
-
letter.style.color = {random_color};
|
229 |
-
letter.style.fontSize = '{new_font_size}';
|
230 |
-
letter.style.transform = 'skew({new_skew}) rotate({new_rotation}) scale(1.1)';
|
231 |
-
letter.style.animation = 'bounce 0.8s ease-in-out, colorShift 2s infinite';
|
232 |
-
letter.style.textShadow = '0px 0px 8px ' + {random_color};
|
233 |
-
}}
|
234 |
-
}}, {i * 100});
|
235 |
-
"""
|
236 |
-
|
237 |
-
animation_script += """
|
238 |
-
}
|
239 |
-
|
240 |
-
// Trigger the animation
|
241 |
-
animateWords();
|
242 |
-
</script>
|
243 |
-
"""
|
244 |
-
|
245 |
-
# Add the script to the HTML
|
246 |
-
if "</body>" in input_html:
|
247 |
-
updated_html = input_html.replace("</body>", animation_script + "</body>")
|
248 |
-
else:
|
249 |
-
updated_html = input_html + animation_script
|
250 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
251 |
return updated_html
|
252 |
|
253 |
# Create Gradio interface using Blocks
|
254 |
with gr.Blocks() as demo:
|
255 |
-
gr.Markdown("# Random Word Styler\nGenerate 5 random styled words
|
256 |
|
257 |
generate_button = gr.Button("Generate Random Words", variant="primary")
|
258 |
output_html = gr.HTML()
|
|
|
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 |
"'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",
|
|
|
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 |
+
style['animation'] = f'{animation_name} 0.8s ease-in-out infinite'
|
101 |
+
style['animation-delay'] = f'{i * 0.15}s'
|
102 |
+
|
103 |
style_str = '; '.join([f'{k}: {v}' for k, v in style.items()])
|
104 |
+
styled_letter = f'<span class="styled-letter" style="{style_str}">{letter}</span>'
|
105 |
styled_letters.append(styled_letter)
|
106 |
|
107 |
+
# Create keyframes for movement animation
|
108 |
+
keyframes = f"""
|
109 |
+
<style>
|
110 |
+
@keyframes {animation_name} {{
|
111 |
+
0% {{ transform: scale(1) rotate(0deg) skew({random.choice(skew_angles)}); }}
|
112 |
+
25% {{ transform: scale(1.3) rotate({random.choice(["-15deg", "15deg", "20deg"])}deg) skew({random.choice(skew_angles)}); }}
|
113 |
+
50% {{ transform: scale(0.9) rotate({random.choice(["-10deg", "10deg", "25deg"])}deg) skew({random.choice(skew_angles)}); }}
|
114 |
+
75% {{ transform: scale(1.2) rotate({random.choice(["-5deg", "5deg", "30deg"])}deg) skew({random.choice(skew_angles)}); }}
|
115 |
+
100% {{ transform: scale(1.1) rotate(0deg) skew({random.choice(skew_angles)}); }}
|
116 |
+
}}
|
117 |
+
</style>
|
118 |
+
""" if use_color else ""
|
119 |
|
120 |
return f'''
|
121 |
+
{keyframes}
|
122 |
<span class="word-container" id="word-{word_id}" style="display: inline-block;
|
123 |
margin: 10px;
|
124 |
padding: 8px 12px;
|
|
|
134 |
|
135 |
def generate_random_words():
|
136 |
"""Generate 5 random words with initial styling."""
|
137 |
+
global original_word_designs, selected_words
|
138 |
|
139 |
# Reset data
|
140 |
+
original_word_designs = {}
|
141 |
selected_words = random.sample(SPECIAL_WORDS, 5)
|
142 |
|
143 |
styled_words = []
|
144 |
for i, word in enumerate(selected_words):
|
145 |
+
# Generate original design (black)
|
146 |
+
original_design = generate_word_design(word, i, use_color=False)
|
147 |
+
original_word_designs[i] = original_design
|
148 |
+
styled_words.append(original_design)
|
149 |
|
150 |
final_output = f"""
|
151 |
<html>
|
|
|
174 |
font-family: "Josefin Sans", sans-serif;
|
175 |
padding: 20px;
|
176 |
}}
|
177 |
+
.styled-letter {{
|
178 |
+
transition: all 0.6s ease;
|
|
|
|
|
|
|
|
|
|
|
|
|
179 |
}}
|
180 |
</style>
|
181 |
</head>
|
182 |
<body>
|
183 |
<div style='max-width: 800px; margin: auto; text-align: center;'>
|
184 |
<h2 style="margin-bottom: 30px;">Random Styled Words</h2>
|
185 |
+
<div id="words-container" style="display: flex; flex-wrap: wrap; justify-content: center; align-items: center;">
|
186 |
{" ".join(styled_words)}
|
187 |
</div>
|
188 |
</div>
|
|
|
193 |
return final_output
|
194 |
|
195 |
def trigger_movement(input_html):
|
196 |
+
"""Function to trigger the movement by replacing each word with a completely NEW styled version."""
|
197 |
+
global original_word_designs, selected_words
|
198 |
|
199 |
+
if not original_word_designs or not selected_words:
|
200 |
return input_html
|
201 |
|
202 |
+
updated_html = input_html
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
203 |
|
204 |
+
# Replace each word with its completely new animated version
|
205 |
+
for i, word in enumerate(selected_words):
|
206 |
+
if i in original_word_designs:
|
207 |
+
# Generate COMPLETELY NEW design with color and animation
|
208 |
+
new_movement_design = generate_word_design(word, i, use_color=True)
|
209 |
+
# Replace the original design with the new one
|
210 |
+
updated_html = updated_html.replace(original_word_designs[i], new_movement_design, 1)
|
211 |
+
|
212 |
return updated_html
|
213 |
|
214 |
# Create Gradio interface using Blocks
|
215 |
with gr.Blocks() as demo:
|
216 |
+
gr.Markdown("# Random Word Styler\nGenerate 5 random styled words that transform into completely new styles!")
|
217 |
|
218 |
generate_button = gr.Button("Generate Random Words", variant="primary")
|
219 |
output_html = gr.HTML()
|