circulartext's picture
Update app.py
aa9287d verified
raw
history blame
15.5 kB
import gradio as gr
import random
# Your predefined words list
SPECIAL_WORDS = [
'movie', 'excited', 'waiting', 'long', 'time', 'production', 'real', 'coded', 'digital', 'favorite',
'asking', 'doing', 'basketball', 'soccer', 'football', 'baseball', 'soup', 'food', 'burgers', 'pizza',
'fruit', 'pineapple', 'milk', 'jello', 'candy', 'rice', 'greens', 'lettuce', 'oatmeal', 'cereal',
'dogs', 'cats', 'animals', 'goats', 'sheep', 'movies', 'money', 'bank', 'account', 'keeping',
'looking', 'moving', 'boxes', 'elephants', 'movement', 'coding', 'developing', 'going', 'cruise',
'ship', 'boat', 'bahamas', 'foods', 'healthy', 'eating', 'important', 'pennsylvania', 'atlanta',
'north carolina', 'new york', 'france', 'paris', 'work', 'jobs', 'computers', 'computer', 'grocery',
'glamorous', 'version', 'truck', 'pickup', 'play', 'types', 'games', 'applications', 'quantum',
'speeds', 'advancements', 'technological', 'glimpse', 'countless', 'technology', 'future', 'walking',
'hello', 'jordan', 'season', 'superstar', 'nba', 'championship', 'leading', 'points', 'assist',
'career', 'chicago', 'scared', 'tongue', 'energy', 'disguise', 'business', 'older', 'grown', 'call',
'bills', 'garden', 'house', 'fallen', 'blossoms', 'lawn', 'love', 'forever', 'most', 'fan', 'clout',
'space', 'team', 'today', 'woke', 'work', 'relax', 'quicker', 'thicker', 'richer', 'data', 'ballet',
'dancer', 'goat', 'post', 'lebron', 'james', 'eagles', 'rockets', 'times', 'tank', 'pencil', 'watch',
'rolex', 'rappers', 'rockstar', 'rocket', 'rocks', 'tooth', 'teeth', 'pancake', 'breakfast', 'lunch',
'dinner', 'zoom', 'calling', 'talking', 'rule', 'ruler', 'rick', 'morty', 'martin', 'smith', 'wild',
'track', 'field', 'touchdown', 'basket', 'hope', 'yours', 'thank', 'olympics', 'sports', 'help',
'legal', 'law', 'firm', 'crowd', 'winner', 'winter', 'smoking', 'green', 'purple', 'blue', 'pink',
'orange', 'black', 'white', 'yellow', 'gold', 'weather', 'sun', 'middle', 'summer', 'heat', 'spring'
]
# Global variables
original_designs = {}
selected_words = []
def generate_word_design(word, word_id, is_animated=False):
"""Generate styled design for a word."""
fonts = [
"'VT323', monospace",
"'Josefin Sans', sans-serif",
"'Rajdhani', sans-serif",
"'Anton', sans-serif",
"'Caveat', cursive",
"'Patrick Hand', cursive",
"'Nothing You Could Do', cursive",
"'Reenie Beanie', cursive",
"'Orbitron', sans-serif",
"'Raleway', sans-serif",
"'Open Sans Condensed', sans-serif",
"'Poiret One', cursive",
"'Indie Flower', cursive",
"'Pacifico', cursive",
"'Teko', sans-serif"
]
if not is_animated:
# Original state values
font_sizes = ["18px", "19px", "20px"]
font_tops = ["0px", "1px", "-1px"]
letter_spacings = ["-1px", "0px", "1px", "2px"]
text_shadows = ["0px 0px 1px #000", "0px 0px 2px #000", "1px 0px 0px #000", "0px 0px 0px #000"]
skew_angles = ["-25deg", "-20deg", "-15deg", "-10deg", "0deg", "10deg", "15deg", "20deg", "25deg"]
word_color = "#000000" # All letters in original word are black
else:
# Animated state values
font_sizes = ["20px", "22px", "24px", "26px"]
font_tops = ["-3px", "0px", "3px", "5px"]
letter_spacings = ["-3px", "-2px", "0px", "2px", "3px", "4px"]
text_shadows = ["0px 0px 5px", "2px 2px 4px", "0px 0px 8px", "3px 3px 6px", "1px 1px 10px"]
skew_angles = ["-35deg", "-25deg", "0deg", "25deg", "35deg", "45deg"]
word_color = f"#{random.randint(0, 0xFFFFFF):06x}" # ONE color for the entire word
letters = list(word)
styled_letters = []
keyframes_css = ""
if is_animated:
# Get original styles to create transition keyframes
original_data = original_designs.get(word_id, {})
for i, letter in enumerate(letters):
if not is_animated:
# Store original values for later animation
if word_id not in original_designs:
original_designs[word_id] = {'letters': [], 'word_color': word_color}
original_styles = {
'font_family': random.choice(fonts),
'font_size': random.choice(font_sizes),
'letter_spacing': random.choice(letter_spacings),
'text_shadow': random.choice(text_shadows),
'skew_angle': random.choice(skew_angles),
'margin_top': random.choice(["-0.02cm", "0.00cm", "0.02cm"]),
'top': random.choice(font_tops),
'color': word_color # Same color for all letters in this word
}
original_designs[word_id]['letters'].append(original_styles)
original_designs[word_id]['word_color'] = word_color
style = {
'font-family': original_styles['font_family'],
'line-height': '1.6',
'font-size': original_styles['font_size'],
'letter-spacing': original_styles['letter_spacing'],
'text-shadow': original_styles['text_shadow'],
'transform': f'skew({original_styles["skew_angle"]})',
'margin-top': original_styles['margin_top'],
'position': 'relative',
'top': original_styles['top'],
'color': original_styles['color'],
'display': 'inline-block',
'margin': '0 1px',
'vertical-align': 'middle'
}
else:
# Create animated version with keyframes
original_letter_styles = original_data['letters'][i] if i < len(original_data.get('letters', [])) else {}
original_word_color = original_data.get('word_color', '#000000')
# New target values (but same color for all letters in this word)
new_font_family = random.choice(fonts)
new_font_size = random.choice(font_sizes)
new_letter_spacing = random.choice(letter_spacings)
new_text_shadow = f"{random.choice(text_shadows)} {word_color}" # Use word_color for shadow
new_skew_angle = random.choice(skew_angles)
new_top = random.choice(font_tops)
new_margin_top = random.choice(["-0.05cm", "0.00cm", "0.03cm", "0.05cm"])
# Create unique animation name
animation_name = f"move_{word_id}_{i}_{random.randint(1000, 9999)}"
# Get original values for keyframes
orig_font_size = original_letter_styles.get('font_size', '18px')
orig_letter_spacing = original_letter_styles.get('letter_spacing', '0px')
orig_color = original_letter_styles.get('color', '#000000')
orig_text_shadow = original_letter_styles.get('text_shadow', '0px 0px 0px #000')
orig_skew_angle = original_letter_styles.get('skew_angle', '0deg')
orig_top = original_letter_styles.get('top', '0px')
orig_margin_top = original_letter_styles.get('margin_top', '0.00cm')
# Create keyframes that transition from original to new values
keyframes_css += f"""
@keyframes {animation_name} {{
0% {{
font-size: {orig_font_size};
letter-spacing: {orig_letter_spacing};
color: {orig_color};
text-shadow: {orig_text_shadow};
transform: skew({orig_skew_angle}) scale(1);
top: {orig_top};
margin-top: {orig_margin_top};
}}
25% {{
font-size: {new_font_size};
letter-spacing: {new_letter_spacing};
color: {word_color};
text-shadow: {new_text_shadow};
transform: skew({new_skew_angle}) scale(1.2);
top: {new_top};
margin-top: {new_margin_top};
}}
50% {{
transform: skew({new_skew_angle}) scale(0.9);
}}
75% {{
transform: skew({new_skew_angle}) scale(1.1);
}}
100% {{
font-size: {new_font_size};
letter-spacing: {new_letter_spacing};
color: {word_color};
text-shadow: {new_text_shadow};
transform: skew({new_skew_angle}) scale(1);
top: {new_top};
margin-top: {new_margin_top};
}}
}}
"""
style = {
'font-family': new_font_family, # Font changes instantly
'line-height': '1.6',
'font-size': new_font_size,
'letter-spacing': new_letter_spacing,
'text-shadow': new_text_shadow,
'transform': f'skew({new_skew_angle})',
'margin-top': new_margin_top,
'position': 'relative',
'top': new_top,
'color': word_color, # Same color for all letters in this word
'display': 'inline-block',
'margin': '0 1px',
'vertical-align': 'middle',
'animation': f'{animation_name} 1.5s ease-in-out forwards',
'animation-delay': f'{i * 0.1}s'
}
style_str = '; '.join([f'{k}: {v}' for k, v in style.items()])
styled_letter = f'<span class="letter-{word_id}-{i}" style="{style_str}">{letter}</span>'
styled_letters.append(styled_letter)
return f'''
{f"<style>{keyframes_css}</style>" if keyframes_css else ""}
<span class="word-container" id="word-{word_id}" style="display: inline-block;
margin: 10px;
padding: 8px 12px;
border: 2px solid #333;
border-radius: 8px;
background-color: rgba(255,255,255,0.8);">
<span style="display: inline-flex;
align-items: baseline;
vertical-align: middle;">
{" ".join(styled_letters)}
</span>
</span>'''
def generate_random_words():
"""Generate 5 random words with initial styling."""
global original_designs, selected_words
# Reset data
original_designs = {}
selected_words = random.sample(SPECIAL_WORDS, 5)
styled_words = []
for i, word in enumerate(selected_words):
word_design = generate_word_design(word, i, is_animated=False)
styled_words.append(word_design)
final_output = f"""
<html>
<head>
<link href="https://fonts.googleapis.com/css2?family=VT323&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Josefin+Sans:wght@100&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Rajdhani:wght@300&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Anton&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Caveat&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Patrick+Hand&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Nothing+You+Could+Do&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Reenie+Beanie&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Orbitron&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Raleway:500" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Open+Sans+Condensed:wght@300&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Poiret+One&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Indie+Flower&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Pacifico&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Teko&display=swap" rel="stylesheet">
<style>
body {{
background-color: #f5f5f5;
color: #000;
font-size: 18px;
line-height: 1.6;
font-family: "Josefin Sans", sans-serif;
padding: 20px;
}}
</style>
</head>
<body>
<div style='max-width: 800px; margin: auto; text-align: center;'>
<h2 style="margin-bottom: 30px;">Random Styled Words</h2>
<div id="words-container" style="display: flex; flex-wrap: wrap; justify-content: center; align-items: center;">
{" ".join(styled_words)}
</div>
</div>
</body>
</html>
"""
return final_output
def trigger_movement(input_html):
"""Replace words with animated versions that transition from original to new styling."""
global original_designs, selected_words
if not original_designs or not selected_words:
return input_html
updated_html = input_html
# Replace each word with its animated version
for i, word in enumerate(selected_words):
if i in original_designs:
# Generate animated version that transitions from original values
animated_design = generate_word_design(word, i, is_animated=True)
# Find and replace the original word container
old_pattern = f'<span class="word-container" id="word-{i}"'
old_end = '</span></span>'
# Find the full original word HTML
start_idx = updated_html.find(old_pattern)
if start_idx != -1:
# Find the end of this word container
temp_html = updated_html[start_idx:]
span_count = 0
end_idx = start_idx
for j, char in enumerate(temp_html):
if temp_html[j:j+5] == '<span':
span_count += 1
elif temp_html[j:j+7] == '</span>':
span_count -= 1
if span_count == 0:
end_idx = start_idx + j + 7
break
if end_idx > start_idx:
old_word_html = updated_html[start_idx:end_idx]
updated_html = updated_html.replace(old_word_html, animated_design, 1)
return updated_html
# Create Gradio interface using Blocks
with gr.Blocks() as demo:
gr.Markdown("# Random Word Styler\nEach word gets ONE color and transitions from original to new styling!")
generate_button = gr.Button("Generate Random Words", variant="primary")
output_html = gr.HTML()
animate_button = gr.Button("Trigger Progressive Movement", variant="secondary")
generate_button.click(generate_random_words, outputs=output_html)
animate_button.click(trigger_movement, inputs=output_html, outputs=output_html)
# Launch the app
demo.launch()