Criador de GIFs para Slack - Toolkit Flexível
Um toolkit para criar GIFs animados otimizados para o Slack. Fornece validadores para as restrições do Slack, primitivas de animação combináveis e utilitários auxiliares opcionais. Aplique estas ferramentas conforme necessário para alcançar a visão criativa.
Requisitos do Slack
O Slack tem requisitos específicos para GIFs com base no seu uso:
GIFs para Mensagens:
- Tamanho máximo: ~2MB
- Dimensões ideais: 480x480
- FPS típico: 15-20
- Limite de cores: 128-256
- Duração: 2-5s
GIFs para Emojis:
- Tamanho máximo: 64KB (limite rigoroso)
- Dimensões ideais: 128x128
- FPS típico: 10-12
- Limite de cores: 32-48
- Duração: 1-2s
GIFs para Emojis são desafiadores - o limite de 64KB é rigoroso. Estratégias que ajudam:
- Limitar a 10-15 quadros no total
- Usar no máximo 32-48 cores
- Manter os designs simples
- Evitar gradientes
- Validar o tamanho do arquivo com frequência
Estrutura do Toolkit
Esta skill fornece três tipos de ferramentas:
- Validadores - Verificam se um GIF atende aos requisitos do Slack
- Primitivas de Animação - Blocos de construção combináveis para movimento (tremer, quicar, mover, caleidoscópio)
- Utilitários Auxiliares - Funções opcionais para necessidades comuns (texto, cores, efeitos)
A liberdade criativa completa está disponível em como essas ferramentas são aplicadas.
Validadores Principais
Para garantir que um GIF atenda às restrições do Slack, use estes validadores:
from core.gif_builder import GIFBuilder
# Após criar seu GIF, verifique se atende aos requisitos
builder = GIFBuilder(width=128, height=128, fps=10)
# ... adicione seus quadros como quiser ...
# Salve e verifique o tamanho
info = builder.save('emoji.gif', num_colors=48, optimize_for_emoji=True)
# O método save avisa automaticamente se o arquivo exceder os limites
# info dict contém: size_kb, size_mb, frame_count, duration_seconds
Validador de tamanho de arquivo:
from core.validators import check_slack_size
# Verifique se o GIF atende aos limites de tamanho
passes, info = check_slack_size('emoji.gif', is_emoji=True)
# Retorna: (True/False, dict com detalhes de tamanho)
Validador de dimensões:
from core.validators import validate_dimensions
# Verifique as dimensões
passes, info = validate_dimensions(128, 128, is_emoji=True)
# Retorna: (True/False, dict com detalhes da dimensão)
Validação completa:
from core.validators import validate_gif, is_slack_ready
# Execute todas as validações
all_pass, results = validate_gif('emoji.gif', is_emoji=True)
# Ou verificação rápida
if is_slack_ready('emoji.gif', is_emoji=True):
print("Pronto para carregar!")
Primitivas de Animação
Estes são blocos de construção combináveis para movimento. Aplique-os a qualquer objeto em qualquer combinação:
Tremer (Shake)
from templates.shake import create_shake_animation
# Tremer um emoji
frames = create_shake_animation(
object_type='emoji',
object_data={'emoji': '😱', 'size': 80},
num_frames=20,
shake_intensity=15,
direction='both' # ou 'horizontal', 'vertical'
)
Quicar (Bounce)
from templates.bounce import create_bounce_animation
# Quicar um círculo
frames = create_bounce_animation(
object_type='circle',
object_data={'radius': 40, 'color': (255, 100, 100)},
num_frames=30,
bounce_height=150
)
Girar / Rotacionar (Spin / Rotate)
from templates.spin import create_spin_animation, create_loading_spinner
# Giro horário
frames = create_spin_animation(
object_type='emoji',
object_data={'emoji': '🔄', 'size': 100},
rotation_type='clockwise',
full_rotations=2
)
# Rotação oscilante
frames = create_spin_animation(rotation_type='wobble', full_rotations=3)
# Spinner de carregamento
frames = create_loading_spinner(spinner_type='dots')
Pulsar / Batimento Cardíaco (Pulse / Heartbeat)
from templates.pulse import create_pulse_animation, create_attention_pulse
# Pulso suave
frames = create_pulse_animation(
object_data={'emoji': '❤️', 'size': 100},
pulse_type='smooth',
scale_range=(0.8, 1.2)
)
# Batimento cardíaco (dupla pulsação)
frames = create_pulse_animation(pulse_type='heartbeat')
# Pulso de atenção para GIFs de emoji
frames = create_attention_pulse(emoji='⚠️', num_frames=20)
Desaparecer (Fade)
from templates.fade import create_fade_animation, create_crossfade
# Aparecer
frames = create_fade_animation(fade_type='in')
# Desaparecer
frames = create_fade_animation(fade_type='out')
# Transição entre dois emojis
frames = create_crossfade(
object1_data={'emoji': '😊', 'size': 100},
object2_data={'emoji': '😂', 'size': 100}
)
Zoom
from templates.zoom import create_zoom_animation, create_explosion_zoom
# Zoom para dentro dramaticamente
frames = create_zoom_animation(
zoom_type='in',
scale_range=(0.1, 2.0),
add_motion_blur=True
)
# Zoom para fora
frames = create_zoom_animation(zoom_type='out')
# Zoom explosivo
frames = create_explosion_zoom(emoji='💥')
Explodir / Fragmentar (Explode / Shatter)
from templates.explode import create_explode_animation, create_particle_burst
# Explosão em rajada
frames = create_explode_animation(
explode_type='burst',
num_pieces=25
)
# Efeito de fragmentação
frames = create_explode_animation(explode_type='shatter')
# Dissolver em partículas
frames = create_explode_animation(explode_type='dissolve')
# Rajada de partículas
frames = create_particle_burst(particle_count=30)
Balançar / Agitar (Wiggle / Jiggle)
from templates.wiggle import create_wiggle_animation, create_excited_wiggle
# Balanço gelatinoso
frames = create_wiggle_animation(
wiggle_type='jello',
intensity=1.0,
cycles=2
)
# Movimento de onda
frames = create_wiggle_animation(wiggle_type='wave')
# Balanço animado para GIFs de emoji
frames = create_excited_wiggle(emoji='🎉')
Deslizar (Slide)
from templates.slide import create_slide_animation, create_multi_slide
# Deslizar da esquerda com ultrapassagem
frames = create_slide_animation(
direction='left',
slide_type='in',
overshoot=True
)
# Deslizar atravessando
frames = create_slide_animation(direction='left', slide_type='across')
# Múltiplos objetos deslizando em sequência
objects = [
{'data': {'emoji': '🎯', 'size': 60}, 'direction': 'left', 'final_pos': (120, 240)},
{'data': {'emoji': '🎪', 'size': 60}, 'direction': 'right', 'final_pos': (240, 240)}
]
frames = create_multi_slide(objects, stagger_delay=5)
Virar (Flip)
from templates.flip import create_flip_animation, create_quick_flip
# Virada horizontal entre dois emojis
frames = create_flip_animation(
object1_data={'emoji': '😊', 'size': 120},
object2_data={'emoji': '😂', 'size': 120},
flip_axis='horizontal'
)
# Virada vertical
frames = create_flip_animation(flip_axis='vertical')
# Virada rápida para GIFs de emoji
frames = create_quick_flip('👍', '👎')
Transformar / Metamorfosear (Morph / Transform)
from templates.morph import create_morph_animation, create_reaction_morph
# Transformação com transição
frames = create_morph_animation(
object1_data={'emoji': '😊', 'size': 100},
object2_data={'emoji': '😂', 'size': 100},
morph_type='crossfade'
)
# Transformação por escala (encolhe enquanto o outro cresce)
frames = create_morph_animation(morph_type='scale')
# Transformação giratória (semelhante a virada 3D)
frames = create_morph_animation(morph_type='spin_morph')
Efeito de Movimento (Move Effect)
from templates.move import create_move_animation
# Movimento linear
frames = create_move_animation(
object_type='emoji',
object_data={'emoji': '🚀', 'size': 60},
start_pos=(50, 240),
end_pos=(430, 240),
motion_type='linear',
easing='ease_out'
)
# Movimento em arco (trajetória parabólica)
frames = create_move_animation(
object_type='emoji',
object_data={'emoji': '⚽', 'size': 60},
start_pos=(50, 350),
end_pos=(430, 350),
motion_type='arc',
motion_params={'arc_height': 150}
)
# Movimento circular
frames = create_move_animation(
object_type='emoji',
object_data={'emoji': '🌍', 'size': 50},
motion_type='circle',
motion_params={
'center': (240, 240),
'radius': 120,
'angle_range': 360 # círculo completo
}
)
# Movimento de onda
frames = create_move_animation(
motion_type='wave',
motion_params={
'wave_amplitude': 50,
'wave_frequency': 2
}
)
# Ou use funções de easing de baixo nível
from core.easing import interpolate, calculate_arc_motion
for i in range(num_frames):
t = i / (num_frames - 1)
x = interpolate(start_x, end_x, t, easing='ease_out')
# Ou: x, y = calculate_arc_motion(start, end, height, t)
Efeito Caleidoscópio (Kaleidoscope Effect)
from templates.kaleidoscope import apply_kaleidoscope, create_kaleidoscope_animation
# Aplicar a um único quadro
kaleido_frame = apply_kaleidoscope(frame, segments=8)
# Ou criar animação caleidoscópica
frames = create_kaleidoscope_animation(
base_frame=my_frame, # ou None para padrão de demonstração
num_frames=30,
segments=8,
rotation_speed=1.0
)
# Efeitos de espelho simples (mais rápidos)
from templates.kaleidoscope import apply_simple_mirror
mirrored = apply_simple_mirror(frame, mode='quad') # Espelho 4 vias
# modos: 'horizontal', 'vertical', 'quad', 'radial'
Para compor primitivas livremente, siga estes padrões:
# Exemplo: Quicar + tremer para impacto
for i in range(num_frames):
frame = create_blank_frame(480, 480, bg_color)
# Movimento de quicar
t_bounce = i / (num_frames - 1)
y = interpolate(start_y, ground_y, t_bounce, 'bounce_out')
# Adicionar tremor no impacto (quando y atinge o chão)
if y >= ground_y - 5:
shake_x = math.sin(i * 2) * 10
x = center_x + shake_x
else:
x = center_x
draw_emoji(frame, '⚽', (x, y), size=60)
builder.add_frame(frame)
Utilitários Auxiliares
Estes são auxiliares opcionais para necessidades comuns. Use, modifique ou substitua estes por implementações personalizadas conforme necessário.
Construtor de GIF (Montagem e Otimização)
from core.gif_builder import GIFBuilder
# Crie o construtor com suas configurações escolhidas
builder = GIFBuilder(width=480, height=480, fps=20)
# Adicione quadros (como você os criou)
for frame in my_frames:
builder.add_frame(frame)
# Salve com otimização
builder.save('output.gif',
num_colors=128,
optimize_for_emoji=False)
Principais características:
- Quantização automática de cores
- Remoção de quadros duplicados
- Avisos de tamanho para limites do Slack
- Modo emoji (otimização agressiva)
Renderização de Texto
Para GIFs pequenos como emojis, a legibilidade do texto é desafiadora. Uma solução comum envolve adicionar contornos:
from core.typography import draw_text_with_outline, TYPOGRAPHY_SCALE
# Texto com contorno (ajuda na legibilidade)
draw_text_with_outline(
frame, "BONK!",
position=(240, 100),
font_size=TYPOGRAPHY_SCALE['h1'], # 60px
text_color=(255, 68, 68),
outline_color=(0, 0, 0),
outline_width=4,
centered=True
)
Para implementar renderização de texto personalizada, use ImageDraw.text() do PIL, que funciona bem para GIFs maiores.
Gerenciamento de Cores
GIFs com aparência profissional geralmente usam paletas de cores coesas:
from core.color_palettes import get_palette
# Obter uma paleta pronta
palette = get_palette('vibrant') # ou 'pastel', 'dark', 'neon', 'professional'
bg_color = palette['background']
text_color = palette['primary']
accent_color = palette['accent']
Para trabalhar com cores diretamente, use tuplas RGB - o que funcionar para o caso de uso.
Efeitos Visuais
Efeitos opcionais para momentos de impacto:
from core.visual_effects import ParticleSystem, create_impact_flash, create_shockwave_rings
# Sistema de partículas
particles = ParticleSystem()
particles.emit_sparkles(x=240, y=200, count=15)
particles.emit_confetti(x=240, y=200, count=20)
# Atualizar e renderizar cada quadro
particles.update()
particles.render(frame)
# Efeito de flash
frame = create_impact_flash(frame, position=(240, 200), radius=100)
# Anéis de onda de choque
frame = create_shockwave_rings(frame, position=(240, 200), radii=[30, 60, 90])
Funções de Easing
Movimento suave usa easing em vez de interpolação linear:
from core.easing import interpolate
# Objeto caindo (acelera)
y = interpolate(start=0, end=400, t=progress, easing='ease_in')
# Objeto aterrissando (desacelera)
y = interpolate(start=0, end=400, t=progress, easing='ease_out')
# Quicando
y = interpolate(start=0, end=400, t=progress, easing='bounce_out')
# Ultrapassagem (elástico)
scale = interpolate(start=0.5, end=1.0, t=progress, easing='elastic_out')
Easings disponíveis: linear, ease_in, ease_out, ease_in_out, bounce_out, elastic_out, back_out (ultrapassagem) e mais em core/easing.py.
Composição de Quadros
Utilitários básicos de desenho, se precisar:
from core.frame_composer import (
create_gradient_background, # Fundos gradientes
draw_emoji_enhanced, # Emoji com sombra opcional
draw_circle_with_shadow, # Formas com profundidade
draw_star # Estrelas de 5 pontas
)
# Fundo gradiente
frame = create_gradient_background(480, 480, top_color, bottom_color)
# Emoji com sombra
draw_emoji_enhanced(frame, '🎉', position=(200, 200), size=80, shadow=True)
Estratégias de Otimização
Quando seu GIF estiver muito grande:
Para GIFs de Mensagens (>2MB):
- Reduza quadros (menor FPS ou duração mais curta)
- Reduza cores (128 → 64 cores)
- Reduza dimensões (480x480 → 320x320)
- Ative a remoção de quadros duplicados
Para GIFs de Emoji (>64KB) - seja agressivo:
- Limite a 10-12 quadros no total
- Use no máximo 32-40 cores
- Evite gradientes (cores sólidas comprimem melhor)
- Simplifique o design (menos elementos)
- Use
optimize_for_emoji=Trueno método save
Exemplos de Padrões de Composição
Reação Simples (Pulsando)
builder = GIFBuilder(128, 128, 10)
for i in range(12):
frame = Image.new('RGB', (128, 128), (240, 248, 255))
# Escala pulsante
scale = 1.0 + math.sin(i * 0.5) * 0.15
size = int(60 * scale)
draw_emoji_enhanced(frame, '😱', position=(64-size//2, 64-size//2),
size=size, shadow=False)
builder.add_frame(frame)
builder.save('reaction.gif', num_colors=40, optimize_for_emoji=True)
# Validar
from core.validators import check_slack_size
check_slack_size('reaction.gif', is_emoji=True)
Impacto com Efeitos
builder = GIFBuilder(480, 480, 20)
for i in range(30):
frame = Image.new('RGB', (480, 480), (255, 255, 255))
t = i / 29 # progresso
if i < 5:
# Quadros iniciais: zoom de ataque
scale = 1.0 + (5 - i) * 0.2
size = int(60 * scale)
x, y = 240, 300 - (5 - i) * 40
elif i == 5:
# Quadro de impacto: flash
frame = create_impact_flash(frame, (240, 240), 150)
x, y = 240, 240
size = 60
else:
# Quadros posteriores: tremor
shake = math.sin((i - 5) * 3) * (15 - (i - 5))
x, y = 240 + shake, 240
size = 60
draw_emoji_enhanced(frame, '💥', (x - size//2, y - size//2),
size=size, shadow=True)
builder.add_frame(frame)
builder.save('impact.gif', num_colors=128)
Transição com Deslizar e Desaparecer
from templates.slide import create_slide_animation
from templates.fade import create_crossfade
# Primeiro: slide in
slide_frames = create_slide_animation(
object_type='emoji',
object_data={'emoji': '😊', 'size': 80},
direction='left',
slide_type='in',
overshoot=False,
num_frames=15
)
# Depois: crossfade para 😂
crossfade_frames = create_crossfade(
object1_data={'emoji': '😊', 'size': 80},
object2_data={'emoji': '😂', 'size': 80},
num_frames=10
)
# Combinar todas as sequências
builder = GIFBuilder(128, 128, 10)
for frame in slide_frames:
builder.add_frame(frame)
for frame in crossfade_frames:
builder.add_frame(frame)
builder.save('reaction_sequence.gif', num_colors=40, optimize_for_emoji=True)
Boas Práticas e Dicas
Diretrizes de Design
- Comece pequeno - Para emojis, sempre comece com 10-12 quadros. É mais fácil adicionar do que remover.
- Valide cedo, valide frequentemente - Use
check_slack_size()no meio do processo. - Evite gradientes para emojis - Eles são grandes em termos de compressão. Use cores sólidas.
- Use desfoque de movimento com moderação - Pode aumentar significativamente o tamanho do arquivo.
- Regra de ouro para emojis: mais simples é melhor - Emojis com designs limpos e cores limitadas têm melhor desempenho.
Escolha de Primitivas
- Para chamar a atenção: Pulse, Wiggle, Explode
- Para movimento: Shake, Bounce, Slide, Move
- Para transformação: Morph, Flip, Fade
- Para efeitos: Kaleidoscope, Zoom, Particle Effects
Combinações Criativas
- Bounce + Shake = Impacto (bola quicando que treme ao pousar)
- Slide + Fade = Aparição suave (deslizar enquanto aparece)
- Pulse + Wiggle = Entusiasmo (emoji animado pulsando)
- Spin + Zoom = Revelação dramática (girar enquanto aumenta)
- Kaleidoscope + Rotate = Efeito hipnótico
Lembre-se: Todas as primitivas podem ser combinadas, encadeadas, sobrepostas e personalizadas. Essas ferramentas são blocos de construção - sinta-se à vontade para adaptá-las de qualquer forma que atinja sua visão criativa.
Tratamento de Erros
from core.exceptions import SlackGIFError, SizeLimitError
try:
builder.save('output.gif')
except SizeLimitError as e:
print(f"GIF muito grande: {e.size_kb}KB")
print(f"Limite: {e.limit_kb}KB")
# Aplicar otimizações
except SlackGIFError as e:
print(f"Erro de validação: {e}")
Personalização Avançada
Para controle total sobre a animação:
# Modificar parâmetros de movimento existentes
from templates.shake import ShakeConfig
config = ShakeConfig(
intensity=20,
frequency=3.0,
decay=0.95, # tremor diminui com o tempo
direction='both'
)
frames = create_shake_animation(
object_type='emoji',
object_data={'emoji': '😱', 'size': 80},
num_frames=30,
config=config
)
Para animações complexas que exigem controle quadro a quadro, use a abordagem de composição direta:
for i in range(num_frames):
frame = create_base_frame()
# Aplicar múltiplos efeitos
frame = apply_effect1(frame, params_i1)
frame = apply_effect2(frame, params_i2)
builder.add_frame(frame)
Recursos-chave:
core/frame_composer.py- Utilitários de composição de quadroscore/easing.py- Funções de easing para movimento suavecore/color_palettes.py- Paletas de cores predefinidascore/visual_effects.py- Efeitos especiais (partículas, flashes)core/typography.py- Utilitários de texto com contorno para legibilidade