| name | slack-gif-creator |
| description | 面向 Slack 优化的动图制作工具包,内置尺寸校验器与可组合的动画基元。当用户提出“帮我做一个在 Slack 上展示 X 做 Y 的 GIF”之类的请求时,即应使用本技能生成 Slack 动图或表情动画。 |
| license | 完整条款见 LICENSE.txt |
Slack GIF 生成器 - 灵活的工具箱
一个专为 Slack 优化的动图工具包,提供 Slack 约束校验器、可组合的动画基元,以及可选的辅助工具。可根据创意任意组合这些工具,实现目标效果。
Slack 的动图要求
Slack 对不同用途的 GIF 有特定要求:
消息动图:
- 文件大小上限约 2MB
- 最佳尺寸:480×480
- 常见帧率:15-20 FPS
- 色彩限制:128-256
- 推荐时长:2-5 秒
表情动图:
- 文件大小上限 64KB(非常严格)
- 最佳尺寸:128×128
- 常见帧率:10-12 FPS
- 色彩限制:32-48
- 推荐时长:1-2 秒
表情动图特别困难——64KB 限制极其严格。建议策略:
- 总帧数控制在 10-15 帧
- 色彩数量不超过 32-48
- 设计尽量简洁
- 避免渐变
- 频繁检查文件大小
工具箱结构
本技能提供三类工具:
- 校验器 —— 检查 GIF 是否符合 Slack 要求
- 动画基元 —— 可组合的动效组件(抖动、弹跳、移动、万花筒等)
- 辅助工具 —— 可选的通用函数(文字、配色、特效等)
如何组合完全由创意决定。
核心校验器
要确保 GIF 满足 Slack 限制,可使用以下校验器:
from core.gif_builder import GIFBuilder
builder = GIFBuilder(width=128, height=128, fps=10)
info = builder.save('emoji.gif', num_colors=48, optimize_for_emoji=True)
文件大小校验:
from core.validators import check_slack_size
passes, info = check_slack_size('emoji.gif', is_emoji=True)
尺寸校验:
from core.validators import validate_dimensions
passes, info = validate_dimensions(128, 128, is_emoji=True)
完整校验:
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
frames = create_shake_animation(
object_type='emoji',
object_data={'emoji': '😱', 'size': 80},
num_frames=20,
shake_intensity=15,
direction='both'
)
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')
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')
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')
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
)
frames = create_slide_animation(direction='left', slide_type='across')
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
frames = create_flip_animation(
object1_data={'emoji': '😊', 'size': 120},
object2_data={'emoji': '😂', 'size': 120},
flip_axis='horizontal'
)
frames = create_flip_animation(flip_axis='vertical')
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')
frames = create_morph_animation(morph_type='spin_morph')
Move Effect(运动轨迹)
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
}
)
frames = create_move_animation(
motion_type='wave',
motion_params={
'wave_amplitude': 50,
'wave_frequency': 2
}
)
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')
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,
num_frames=30,
segments=8,
rotation_speed=1.0
)
from templates.kaleidoscope import apply_simple_mirror
mirrored = apply_simple_mirror(frame, mode='quad')
自由组合基元可参考以下模式:
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 Builder(组装与优化)
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)
主要特性:
- 自动色彩量化
- 删除重复帧
- 超限时发出警告
- Emoji 模式(更激进的压缩)
文字渲染
对于小尺寸(如表情动图),文字可读性很难保证。常见做法是加描边:
from core.typography import draw_text_with_outline, TYPOGRAPHY_SCALE
draw_text_with_outline(
frame, "BONK!",
position=(240, 100),
font_size=TYPOGRAPHY_SCALE['h1'],
text_color=(255, 68, 68),
outline_color=(0, 0, 0),
outline_width=4,
centered=True
)
如需自定义文字,可直接使用 PIL 的 ImageDraw.text(),适用于较大动图。
色彩管理
专业动图通常使用和谐的调色板:
from core.color_palettes import get_palette
palette = get_palette('vibrant')
bg_color = palette['background']
text_color = palette['primary']
accent_color = palette['accent']
也可直接使用 RGB 元组,按需求取用。
视觉特效
用于强调时刻的可选特效:
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])
缓动函数
为了获得流畅运动,应使用缓动而非线性插值:
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(过冲)等,详见 core/easing.py。
帧合成
如需基础绘制工具,可使用:
from core.frame_composer import (
create_gradient_background,
draw_emoji_enhanced,
draw_circle_with_shadow,
draw_star
)
frame = create_gradient_background(480, 480, top_color, bottom_color)
draw_emoji_enhanced(frame, '🎉', position=(200, 200), size=80, shadow=True)
优化策略
若 GIF 过大,可尝试:
消息动图(>2MB)
- 减少帧数(降低 FPS 或缩短时长)
- 减少色彩(从 128 降到 64)
- 调整尺寸(480×480 → 320×320)
- 启用重复帧去重
表情动图(>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)
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)
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)
组合基元(移动 + 抖动)
from templates.shake import create_shake_animation
shake_frames = create_shake_animation(
object_type='emoji',
object_data={'emoji': '😰', 'size': 70},
num_frames=20,
shake_intensity=12
)
builder = GIFBuilder(480, 480, 20)
for i in range(40):
t = i / 39
if i < 20:
frame = create_blank_frame(480, 480, (255, 255, 255))
x = interpolate(50, 300, t * 2, 'linear')
draw_emoji_enhanced(frame, '🚗', position=(int(x), 300), size=60)
draw_emoji_enhanced(frame, '😰', position=(350, 200), size=70)
else:
frame = shake_frames[i - 20]
draw_emoji_enhanced(frame, '🚗', position=(300, 300), size=60)
builder.add_frame(frame)
builder.save('scare.gif')
制作理念
本工具箱提供的是“组件”,而非固定模板。制作 GIF 时:
- 理解创意目标 —— 想表现什么?整体氛围如何?
- 设计动画结构 —— 分解为预备、动作、反应等阶段
- 按需组合基元 —— 抖动、弹跳、移动、特效任意叠加
- 验证限制 —— 特别注意表情动图的大小
- 必要时迭代 —— 超出限制时减少帧数 / 色彩
目标是在 Slack 的技术约束内,保持创作自由。
依赖项
如需使用本工具箱,请确保安装以下依赖(若已安装可跳过):
pip install pillow imageio numpy