Spaces:
Build error
Build error
| import gradio as gr | |
| import random | |
| # Your predefined words list | |
| SPECIAL_WORDS = [ | |
| 'pikachu', 'charizard', 'bulbasaur', 'squirtle', 'mewtwo', 'mew', 'eevee', 'snorlax', 'jigglypuff', 'gengar', | |
| 'alakazam', 'machamp', 'dragonite', 'gyarados', 'lapras', 'articuno', 'zapdos', 'moltres', 'ditto', 'vaporeon', | |
| 'jolteon', 'flareon', 'umbreon', 'espeon', 'lucario', 'garchomp', 'greninja', 'rayquaza', 'kyogre', 'groudon', | |
| 'dialga', 'palkia', 'giratina', 'arceus', 'reshiram', 'zekrom', 'kyurem', 'xerneas', 'yveltal', 'zygarde', | |
| 'solgaleo', 'lunala', 'necrozma', 'zacian', 'zamazenta', 'eternatus', 'koraidon', 'miraidon', 'meowth', 'psyduck', | |
| 'pokemon', 'trainer', 'evolution', 'pokeball', 'great', 'ultra', 'master', 'pokedex', 'gym', 'leader', | |
| 'champion', 'elite', 'four', 'professor', 'oak', 'ash', 'ketchum', 'misty', 'brock', 'team', | |
| 'rocket', 'jessie', 'james', 'giovanni', 'lance', 'cynthia', 'red', 'blue', 'gary', 'battle', | |
| 'wild', 'legendary', 'mythical', 'shiny', 'mega', 'gigantamax', 'dynamax', 'type', 'fire', 'water', | |
| 'grass', 'electric', 'psychic', 'dragon', 'ghost', 'dark', 'fairy', 'fighting', 'flying', 'kanto', | |
| 'johto', 'hoenn', 'sinnoh', 'unova', 'kalos', 'alola', 'galar', 'paldea', 'region', 'pallet', | |
| 'town', 'viridian', 'city', 'cerulean', 'vermilion', 'lavender', 'celadon', 'saffron', 'fuchsia', 'cinnabar', | |
| 'island', 'indigo', 'plateau', 'victory', 'road', 'pokemon', 'center', 'mart', 'league', 'starter', | |
| 'charmander', 'rattata', 'pidgey', 'caterpie', 'weedle', 'kakuna', 'metapod', 'butterfree', 'beedrill', 'potion', | |
| 'revive', 'rare', 'candy', 'technical', 'machine', 'hidden', 'ability', 'nature', 'stats', 'attack', | |
| 'defense', 'speed', 'special', 'hp', 'experience', 'level', 'catch', 'faint', 'status', 'paralysis', | |
| 'poison', 'burn', 'freeze', 'sleep', 'confusion', 'move', 'physical', 'competitive', 'tournament', 'badge'] | |
| # 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", | |
| "'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 = ["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 = 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} 2.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() |