Slack GIF 创建器(Slack GIF Creator)
一个为 Slack 创建动画 GIF 的工具套件,提供针对 Slack 约束的验证器、可组合的动画原语和可选的辅助工具。当用户请求 Slack 动画 GIF 或表情动画时适用,例如"给我做一个 X 做 Y 的 GIF 用于 Slack"。
Slack 的要求
Slack 根据用途对 GIF 有特定要求:
消息 GIF(Message GIF):
- 最大大小:约 2MB
- 最佳尺寸:480x480
- 典型帧率:15-20 FPS
- 颜色限制:128-256 色
- 时长:2-5 秒
表情 GIF(Emoji GIF):
- 最大大小:64KB(严格限制)
- 最佳尺寸:128x128
- 典型帧率:10-12 FPS
- 颜色限制:32-48 色
- 时长:1-2 秒
表情 GIF 的挑战 —— 64KB 限制非常严格。有帮助的策略:
- 限制总帧数为 10-15 帧
- 最多使用 32-48 色
- 保持设计简洁
- 避免渐变
- 频繁验证文件大小
工具套件结构
本技能提供三类工具:
- 验证器(Validators) - 检查 GIF 是否满足 Slack 要求
- 动画原语(Animation Primitives) - 可组合的运动构建模块(抖动、弹跳、移动、万花筒)
- 辅助工具(Helper Utilities) - 用于常见需求的可选函数(文字、颜色、效果)
在如何应用这些工具上有完全的创意自由。
核心验证器
确保 GIF 满足 Slack 约束:
from core.gif_builder import GIFBuilder
# 创建 GIF 后检查是否满足要求
builder = GIFBuilder(width=128, height=128, fps=10)
# ... 按你的方式添加帧 ...
# 保存并检查大小
info = builder.save('emoji.gif', num_colors=48, optimize_for_emoji=True)
# save 方法会在文件超出限制时自动警告
# info 字典包含:size_kb, size_mb, frame_count, duration_seconds
文件大小验证器:
from core.validators import check_slack_size
# 检查 GIF 是否满足大小限制
passes, info = check_slack_size('emoji.gif', is_emoji=True)
# 返回:(True/False, 包含大小详情的字典)
尺寸验证器:
from core.validators import validate_dimensions
passes, info = validate_dimensions(128, 128, is_emoji=True)
# 返回:(True/False, 包含尺寸详情的字典)
完整验证:
from core.validators import validate_gif, is_slack_ready
# 运行所有验证
all_pass, results = validate_gif('emoji.gif', is_emoji=True)
# 或快速检查
if is_slack_ready('emoji.gif', is_emoji=True):
print("Ready to upload!(可以上传了!)")
动画原语
这些是可组合的运动构建模块。可以将它们以任意组合应用到任何对象上:
抖动(Shake)
from templates.shake import create_shake_animation
# 让一个 emoji 抖动
frames = create_shake_animation(
object_type='emoji',
object_data={'emoji': '😱', 'size': 80},
num_frames=20,
shake_intensity=15,
direction='both' # 或 'horizontal'(水平)、'vertical'(垂直)
)
弹跳(Bounce)
from templates.bounce import create_bounce_animation
# 让一个圆弹跳
frames = create_bounce_animation(
object_type='circle',
object_data={'radius': 40, 'color': (255, 100, 100)},
num_frames=30,
bounce_height=150
)
旋转(Spin / Rotate)
from templates.spin import create_spin_animation, create_loading_spinner
# 顺时针旋转
frames = create_spin_animation(
object_type='emoji',
object_data={'emoji': '🔄', 'size': 100},
rotation_type='clockwise',
full_rotations=2
)
# 摆动旋转
frames = create_spin_animation(rotation_type='wobble', full_rotations=3)
# 加载旋转器
frames = create_loading_spinner(spinner_type='dots')
脉冲 / 心跳(Pulse / Heartbeat)
from templates.pulse import create_pulse_animation, create_attention_pulse
# 平滑脉冲
frames = create_pulse_animation(
object_data={'emoji': '❤️', 'size': 100},
pulse_type='smooth',
scale_range=(0.8, 1.2)
)
# 心跳(双次泵动)
frames = create_pulse_animation(pulse_type='heartbeat')
# 用于表情 GIF 的注意力脉冲
frames = create_attention_pulse(emoji='⚠️', num_frames=20)
淡入淡出(Fade)
from templates.fade import create_fade_animation, create_crossfade
# 淡入
frames = create_fade_animation(fade_type='in')
# 淡出
frames = create_fade_animation(fade_type='out')
# 两个 emoji 之间的交叉淡化
frames = create_crossfade(
object1_data={'emoji': '😊', 'size': 100},
object2_data={'emoji': '😂', 'size': 100}
)
缩放(Zoom)
from templates.zoom import create_zoom_animation, create_explosion_zoom
# 戏剧性放大
frames = create_zoom_animation(
zoom_type='in',
scale_range=(0.1, 2.0),
add_motion_blur=True
)
# 缩小
frames = create_zoom_animation(zoom_type='out')
# 爆炸式缩放
frames = create_explosion_zoom(emoji='💥')
爆炸 / 碎裂(Explode / Shatter)
from templates.explode import create_explode_animation, create_particle_burst
# 爆裂
frames = create_explode_animation(explode_type='burst', num_pieces=25)
# 碎裂效果
frames = create_explode_animation(explode_type='shatter')
# 溶解为粒子
frames = create_explode_animation(explode_type='dissolve')
# 粒子爆发
frames = create_particle_burst(particle_count=30)
摇摆 / 抖动(Wiggle / Jiggle)
from templates.wiggle import create_wiggle_animation, create_excited_wiggle
# 果冻摇晃
frames = create_wiggle_animation(
wiggle_type='jello',
intensity=1.0,
cycles=2
)
# 波浪运动
frames = create_wiggle_animation(wiggle_type='wave')
# 用于表情 GIF 的兴奋摇摆
frames = create_excited_wiggle(emoji='🎉')
滑动(Slide)
from templates.slide import create_slide_animation, create_multi_slide
# 从左侧滑入(带过冲效果)
frames = create_slide_animation(
direction='left',
slide_type='in',
overshoot=True
)
# 多个对象依次滑入
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)
翻转(Flip)
from templates.flip import create_flip_animation, create_quick_flip
# 两个 emoji 之间的水平翻转
frames = create_flip_animation(
object1_data={'emoji': '😊', 'size': 120},
object2_data={'emoji': '😂', 'size': 120},
flip_axis='horizontal'
)
# 用于表情 GIF 的快速翻转
frames = create_quick_flip('👍', '👎')
变形 / 变换(Morph / Transform)
from templates.morph import create_morph_animation, create_reaction_morph
# 交叉淡化变形
frames = create_morph_animation(
object1_data={'emoji': '😊', 'size': 100},
object2_data={'emoji': '😂', 'size': 100},
morph_type='crossfade'
)
# 缩放变形(一个缩小同时另一个放大)
frames = create_morph_animation(morph_type='scale')
# 旋转变形(类 3D 翻转)
frames = create_morph_animation(morph_type='spin_morph')
移动效果(Move)
from templates.move import create_move_animation
# 线性移动
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'
)
# 弧线移动(抛物线轨迹)
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}
)
# 圆周运动
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 # 完整圆
}
)
万花筒效果(Kaleidoscope)
from templates.kaleidoscope import apply_kaleidoscope, create_kaleidoscope_animation
# 应用到单帧
kaleido_frame = apply_kaleidoscope(frame, segments=8)
# 或创建动画万花筒
frames = create_kaleidoscope_animation(
base_frame=my_frame, # 或 None 使用演示图案
num_frames=30,
segments=8,
rotation_speed=1.0
)
# 简单镜像效果(更快)
from templates.kaleidoscope import apply_simple_mirror
mirrored = apply_simple_mirror(frame, mode='quad') # 4 向镜像
# 模式:'horizontal'(水平)、'vertical'(垂直)、'quad'(四向)、'radial'(径向)
自由组合原语
# 示例:弹跳 + 撞击时抖动
for i in range(num_frames):
frame = create_blank_frame(480, 480, bg_color)
# 弹跳运动
t_bounce = i / (num_frames - 1)
y = interpolate(start_y, ground_y, t_bounce, 'bounce_out')
# 落地时添加抖动
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)
辅助工具
这些是用于常见需求的可选辅助工具。可以按需使用、修改或替换为自定义实现。
GIF 构建器(组装与优化)
from core.gif_builder import GIFBuilder
# 使用你选择的设置创建构建器
builder = GIFBuilder(width=480, height=480, fps=20)
# 添加帧(无论你如何创建它们)
for frame in my_frames:
builder.add_frame(frame)
# 保存并优化
builder.save('output.gif', num_colors=128, optimize_for_emoji=False)
关键特性:
- 自动颜色量化
- 重复帧移除
- Slack 限制的大小警告
- 表情模式(激进优化)
文字渲染
对于表情等小型 GIF,文字可读性是一个挑战。常见解决方案是添加描边:
from core.typography import draw_text_with_outline, TYPOGRAPHY_SCALE
# 带描边的文字(提高可读性)
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
)
颜色管理
专业外观的 GIF 通常使用统一的调色板:
from core.color_palettes import get_palette
# 获取预制调色板
palette = get_palette('vibrant') # 或 'pastel'、'dark'、'neon'、'professional'
bg_color = palette['background']
text_color = palette['primary']
accent_color = palette['accent']
视觉效果
用于冲击时刻的可选效果:
from core.visual_effects import ParticleSystem, create_impact_flash, create_shockwave_rings
# 粒子系统
particles = ParticleSystem()
particles.emit_sparkles(x=240, y=200, count=15)
particles.emit_confetti(x=240, y=200, count=20)
# 每帧更新和渲染
particles.update()
particles.render(frame)
# 闪光效果
frame = create_impact_flash(frame, position=(240, 200), radius=100)
# 冲击波环
frame = create_shockwave_rings(frame, position=(240, 200), radii=[30, 60, 90])
缓动函数(Easing Functions)
平滑的运动使用缓动而非线性插值:
from core.easing import interpolate
# 物体下落(加速)
y = interpolate(start=0, end=400, t=progress, easing='ease_in')
# 物体着陆(减速)
y = interpolate(start=0, end=400, t=progress, easing='ease_out')
# 弹跳
y = interpolate(start=0, end=400, t=progress, easing='bounce_out')
# 过冲(弹性)
scale = interpolate(start=0.5, end=1.0, t=progress, easing='elastic_out')
可用缓动类型:linear(线性)、ease_in(渐入)、ease_out(渐出)、ease_in_out(渐入渐出)、bounce_out(弹出)、elastic_out(弹性出)、back_out(过冲)等。
帧合成
基础绘图工具:
from core.frame_composer import (
create_gradient_background, # 渐变背景
draw_emoji_enhanced, # 带可选阴影的 Emoji
draw_circle_with_shadow, # 带深度感的形状
draw_star # 五角星
)
# 渐变背景
frame = create_gradient_background(480, 480, top_color, bottom_color)
# 带阴影的 Emoji
draw_emoji_enhanced(frame, '🎉', position=(200, 200), size=80, shadow=True)
优化策略
当你的 GIF 太大时:
消息 GIF(>2MB):
- 减少帧数(降低帧率或缩短时长)
- 减少颜色(128 → 64 色)
- 减小尺寸(480x480 → 320x320)
- 启用重复帧移除
表情 GIF(>64KB)—— 需要激进优化:
- 限制总帧数为 10-12 帧
- 最多使用 32-40 色
- 避免渐变(纯色压缩效果更好)
- 简化设计(更少元素)
- 在 save 方法中使用
optimize_for_emoji=True
示例组合模式
简单反应(脉冲)
builder = GIFBuilder(128, 128, 10)
for i in range(12):
frame = Image.new('RGB', (128, 128), (240, 248, 255))
# 脉冲缩放
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)
# 验证
from core.validators import check_slack_size
check_slack_size('reaction.gif', is_emoji=True)
带冲击的动作(弹跳 + 闪光)
builder = GIFBuilder(480, 480, 20)
# 阶段 1:物体下落
for i in range(15):
frame = create_gradient_background(480, 480, (240, 248, 255), (200, 230, 255))
t = i / 14
y = interpolate(0, 350, t, 'ease_in')
draw_emoji_enhanced(frame, '⚽', position=(220, int(y)), size=80)
builder.add_frame(frame)
# 阶段 2:撞击 + 闪光
for i in range(8):
frame = create_gradient_background(480, 480, (240, 248, 255), (200, 230, 255))
# 前几帧闪光
if i < 3:
frame = create_impact_flash(frame, (240, 350), radius=120, intensity=0.6)
draw_emoji_enhanced(frame, '⚽', position=(220, 350), size=80)
# 文字出现
if i > 2:
draw_text_with_outline(frame, "GOAL!", position=(240, 150),
font_size=60, text_color=(255, 68, 68),
outline_color=(0, 0, 0), outline_width=4,
centered=True)
builder.add_frame(frame)
builder.save('goal.gif', num_colors=128)
设计理念
本工具套件提供构建模块,而非固定配方。处理 GIF 请求时:
- 理解创意愿景 - 应该发生什么?什么情绪?
- 设计动画 - 分解为阶段(预备、动作、反应)
- 按需应用原语 - 抖动、弹跳、移动、效果——自由混合
- 验证约束 - 检查文件大小,特别是表情 GIF
- 如需迭代 - 如果超出大小限制则减少帧/颜色
目标是在 Slack 的技术约束内实现创意自由。
依赖项
使用此工具套件需要安装以下依赖(如果尚未安装):
pip install pillow imageio numpy