slack-gif-creator
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSlack GIF Creator - Flexible Toolkit
Slack GIF 创建工具包 - 灵活的动图制作工具
A toolkit for creating animated GIFs optimized for Slack. Provides validators for Slack's constraints, composable animation primitives, and optional helper utilities. Apply these tools however needed to achieve the creative vision.
一款专为Slack优化的动图GIF创建工具包,包含Slack约束验证器、可组合的动画基础组件以及可选的辅助工具。可根据创意需求灵活使用这些工具。
Slack's Requirements
Slack的要求
Slack has specific requirements for GIFs based on their use:
Message GIFs:
- Max size: ~2MB
- Optimal dimensions: 480x480
- Typical FPS: 15-20
- Color limit: 128-256
- Duration: 2-5s
Emoji GIFs:
- Max size: 64KB (strict limit)
- Optimal dimensions: 128x128
- Typical FPS: 10-12
- Color limit: 32-48
- Duration: 1-2s
Emoji GIFs are challenging - the 64KB limit is strict. Strategies that help:
- Limit to 10-15 frames total
- Use 32-48 colors maximum
- Keep designs simple
- Avoid gradients
- Validate file size frequently
Slack根据动图的使用场景制定了特定要求:
消息动图:
- 最大文件大小:约2MB
- 最佳尺寸:480x480
- 典型帧率(FPS):15-20
- 颜色限制:128-256色
- 时长:2-5秒
表情动图:
- 最大文件大小:64KB(严格限制)
- 最佳尺寸:128x128
- 典型帧率(FPS):10-12
- 颜色限制:32-48色
- 时长:1-2秒
表情动图制作难度较高——64KB的限制非常严格。以下策略可帮助压缩大小:
- 总帧数限制在10-15帧
- 最多使用32-48种颜色
- 保持设计简洁
- 避免使用渐变
- 频繁验证文件大小
Toolkit Structure
工具包结构
This skill provides three types of tools:
- Validators - Check if a GIF meets Slack's requirements
- Animation Primitives - Composable building blocks for motion (shake, bounce, move, kaleidoscope)
- Helper Utilities - Optional functions for common needs (text, colors, effects)
Complete creative freedom is available in how these tools are applied.
本工具提供三类工具:
- 验证器 - 检查GIF是否符合Slack的要求
- 动画基础组件 - 可组合的动画构建模块(摇晃、弹跳、移动、万花筒效果等)
- 辅助工具 - 满足常见需求的可选功能(文本、颜色、特效)
可完全自由地组合使用这些工具。
Core Validators
核心验证器
To ensure a GIF meets Slack's constraints, use these validators:
python
from core.gif_builder import GIFBuilder为确保GIF符合Slack的约束,请使用以下验证器:
python
from core.gif_builder import GIFBuilderAfter creating your GIF, check if it meets requirements
创建GIF后,检查是否符合要求
builder = GIFBuilder(width=128, height=128, fps=10)
builder = GIFBuilder(width=128, height=128, fps=10)
... add your frames however you want ...
... 按需添加帧 ...
Save and check size
保存并检查大小
info = builder.save('emoji.gif', num_colors=48, optimize_for_emoji=True)
info = builder.save('emoji.gif', num_colors=48, optimize_for_emoji=True)
The save method automatically warns if file exceeds limits
保存方法会在文件超出限制时自动发出警告
info dict contains: size_kb, size_mb, frame_count, duration_seconds
info字典包含:size_kb, size_mb, frame_count, duration_seconds
**File size validator**:
```python
from core.validators import check_slack_size
**文件大小验证器**:
```python
from core.validators import check_slack_sizeCheck if GIF meets size limits
检查GIF是否符合大小限制
passes, info = check_slack_size('emoji.gif', is_emoji=True)
passes, info = check_slack_size('emoji.gif', is_emoji=True)
Returns: (True/False, dict with size details)
返回值:(True/False, 包含大小详情的字典)
**Dimension validator**:
```python
from core.validators import validate_dimensions
**尺寸验证器**:
```python
from core.validators import validate_dimensionsCheck dimensions
检查尺寸
passes, info = validate_dimensions(128, 128, is_emoji=True)
passes, info = validate_dimensions(128, 128, is_emoji=True)
Returns: (True/False, dict with dimension details)
返回值:(True/False, 包含尺寸详情的字典)
**Complete validation**:
```python
from core.validators import validate_gif, is_slack_ready
**完整验证**:
```python
from core.validators import validate_gif, is_slack_readyRun all validations
运行所有验证
all_pass, results = validate_gif('emoji.gif', is_emoji=True)
all_pass, results = validate_gif('emoji.gif', is_emoji=True)
Or quick check
或快速检查
if is_slack_ready('emoji.gif', is_emoji=True):
print("Ready to upload!")
undefinedif is_slack_ready('emoji.gif', is_emoji=True):
print("可上传至Slack!")
undefinedAnimation Primitives
动画基础组件
These are composable building blocks for motion. Apply these to any object in any combination:
这些是可组合的动画构建模块,可应用于任意对象的任意组合:
Shake
摇晃
python
from templates.shake import create_shake_animationpython
from templates.shake import create_shake_animationShake an emoji
让表情摇晃
frames = create_shake_animation(
object_type='emoji',
object_data={'emoji': '😱', 'size': 80},
num_frames=20,
shake_intensity=15,
direction='both' # or 'horizontal', 'vertical'
)
undefinedframes = create_shake_animation(
object_type='emoji',
object_data={'emoji': '😱', 'size': 80},
num_frames=20,
shake_intensity=15,
direction='both' # 可选:'horizontal'(水平), 'vertical'(垂直)
)
undefinedBounce
弹跳
python
from templates.bounce import create_bounce_animationpython
from templates.bounce import create_bounce_animationBounce a circle
让圆形弹跳
frames = create_bounce_animation(
object_type='circle',
object_data={'radius': 40, 'color': (255, 100, 100)},
num_frames=30,
bounce_height=150
)
undefinedframes = create_bounce_animation(
object_type='circle',
object_data={'radius': 40, 'color': (255, 100, 100)},
num_frames=30,
bounce_height=150
)
undefinedSpin / Rotate
旋转
python
from templates.spin import create_spin_animation, create_loading_spinnerpython
from templates.spin import create_spin_animation, create_loading_spinnerClockwise spin
顺时针旋转
frames = create_spin_animation(
object_type='emoji',
object_data={'emoji': '🔄', 'size': 100},
rotation_type='clockwise',
full_rotations=2
)
frames = create_spin_animation(
object_type='emoji',
object_data={'emoji': '🔄', 'size': 100},
rotation_type='clockwise',
full_rotations=2
)
Wobble rotation
摇摆旋转
frames = create_spin_animation(rotation_type='wobble', full_rotations=3)
frames = create_spin_animation(rotation_type='wobble', full_rotations=3)
Loading spinner
加载动画
frames = create_loading_spinner(spinner_type='dots')
undefinedframes = create_loading_spinner(spinner_type='dots')
undefinedPulse / Heartbeat
脉冲/心跳
python
from templates.pulse import create_pulse_animation, create_attention_pulsepython
from templates.pulse import create_pulse_animation, create_attention_pulseSmooth pulse
平滑脉冲
frames = create_pulse_animation(
object_data={'emoji': '❤️', 'size': 100},
pulse_type='smooth',
scale_range=(0.8, 1.2)
)
frames = create_pulse_animation(
object_data={'emoji': '❤️', 'size': 100},
pulse_type='smooth',
scale_range=(0.8, 1.2)
)
Heartbeat (double-pump)
心跳(双脉冲)
frames = create_pulse_animation(pulse_type='heartbeat')
frames = create_pulse_animation(pulse_type='heartbeat')
Attention pulse for emoji GIFs
表情动图的提醒脉冲
frames = create_attention_pulse(emoji='⚠️', num_frames=20)
undefinedframes = create_attention_pulse(emoji='⚠️', num_frames=20)
undefinedFade
淡入淡出
python
from templates.fade import create_fade_animation, create_crossfadepython
from templates.fade import create_fade_animation, create_crossfadeFade in
淡入
frames = create_fade_animation(fade_type='in')
frames = create_fade_animation(fade_type='in')
Fade out
淡出
frames = create_fade_animation(fade_type='out')
frames = create_fade_animation(fade_type='out')
Crossfade between two emojis
两个表情之间的交叉淡入淡出
frames = create_crossfade(
object1_data={'emoji': '😊', 'size': 100},
object2_data={'emoji': '😂', 'size': 100}
)
undefinedframes = create_crossfade(
object1_data={'emoji': '😊', 'size': 100},
object2_data={'emoji': '😂', 'size': 100}
)
undefinedZoom
缩放
python
from templates.zoom import create_zoom_animation, create_explosion_zoompython
from templates.zoom import create_zoom_animation, create_explosion_zoomZoom in dramatically
大幅放大
frames = create_zoom_animation(
zoom_type='in',
scale_range=(0.1, 2.0),
add_motion_blur=True
)
frames = create_zoom_animation(
zoom_type='in',
scale_range=(0.1, 2.0),
add_motion_blur=True
)
Zoom out
缩小
frames = create_zoom_animation(zoom_type='out')
frames = create_zoom_animation(zoom_type='out')
Explosion zoom
爆炸式缩放
frames = create_explosion_zoom(emoji='💥')
undefinedframes = create_explosion_zoom(emoji='💥')
undefinedExplode / Shatter
爆炸/碎裂
python
from templates.explode import create_explode_animation, create_particle_burstpython
from templates.explode import create_explode_animation, create_particle_burstBurst explosion
爆发式爆炸
frames = create_explode_animation(
explode_type='burst',
num_pieces=25
)
frames = create_explode_animation(
explode_type='burst',
num_pieces=25
)
Shatter effect
碎裂效果
frames = create_explode_animation(explode_type='shatter')
frames = create_explode_animation(explode_type='shatter')
Dissolve into particles
溶解为粒子
frames = create_explode_animation(explode_type='dissolve')
frames = create_explode_animation(explode_type='dissolve')
Particle burst
粒子爆发
frames = create_particle_burst(particle_count=30)
undefinedframes = create_particle_burst(particle_count=30)
undefinedWiggle / Jiggle
扭动/抖动
python
from templates.wiggle import create_wiggle_animation, create_excited_wigglepython
from templates.wiggle import create_wiggle_animation, create_excited_wiggleJello wobble
果冻晃动
frames = create_wiggle_animation(
wiggle_type='jello',
intensity=1.0,
cycles=2
)
frames = create_wiggle_animation(
wiggle_type='jello',
intensity=1.0,
cycles=2
)
Wave motion
波浪运动
frames = create_wiggle_animation(wiggle_type='wave')
frames = create_wiggle_animation(wiggle_type='wave')
Excited wiggle for emoji GIFs
表情动图的兴奋抖动
frames = create_excited_wiggle(emoji='🎉')
undefinedframes = create_excited_wiggle(emoji='🎉')
undefinedSlide
滑动
python
from templates.slide import create_slide_animation, create_multi_slidepython
from templates.slide import create_slide_animation, create_multi_slideSlide in from left with overshoot
从左侧滑入并带过冲效果
frames = create_slide_animation(
direction='left',
slide_type='in',
overshoot=True
)
frames = create_slide_animation(
direction='left',
slide_type='in',
overshoot=True
)
Slide across
横向滑动
frames = create_slide_animation(direction='left', slide_type='across')
frames = create_slide_animation(direction='left', slide_type='across')
Multiple objects sliding in sequence
多个对象按顺序滑动
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)
undefinedobjects = [
{'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)
undefinedFlip
翻转
python
from templates.flip import create_flip_animation, create_quick_flippython
from templates.flip import create_flip_animation, create_quick_flipHorizontal flip between two emojis
两个表情之间的水平翻转
frames = create_flip_animation(
object1_data={'emoji': '😊', 'size': 120},
object2_data={'emoji': '😂', 'size': 120},
flip_axis='horizontal'
)
frames = create_flip_animation(
object1_data={'emoji': '😊', 'size': 120},
object2_data={'emoji': '😂', 'size': 120},
flip_axis='horizontal'
)
Vertical flip
垂直翻转
frames = create_flip_animation(flip_axis='vertical')
frames = create_flip_animation(flip_axis='vertical')
Quick flip for emoji GIFs
表情动图的快速翻转
frames = create_quick_flip('👍', '👎')
undefinedframes = create_quick_flip('👍', '👎')
undefinedMorph / Transform
变形/转换
python
from templates.morph import create_morph_animation, create_reaction_morphpython
from templates.morph import create_morph_animation, create_reaction_morphCrossfade morph
交叉淡入淡出变形
frames = create_morph_animation(
object1_data={'emoji': '😊', 'size': 100},
object2_data={'emoji': '😂', 'size': 100},
morph_type='crossfade'
)
frames = create_morph_animation(
object1_data={'emoji': '😊', 'size': 100},
object2_data={'emoji': '😂', 'size': 100},
morph_type='crossfade'
)
Scale morph (shrink while other grows)
缩放变形(一个缩小同时另一个放大)
frames = create_morph_animation(morph_type='scale')
frames = create_morph_animation(morph_type='scale')
Spin morph (3D flip-like)
旋转变形(类3D翻转)
frames = create_morph_animation(morph_type='spin_morph')
undefinedframes = create_morph_animation(morph_type='spin_morph')
undefinedMove Effect
移动效果
python
from templates.move import create_move_animationpython
from templates.move import create_move_animationLinear movement
线性移动
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, 240),
end_pos=(430, 240),
motion_type='linear',
easing='ease_out'
)
Arc movement (parabolic trajectory)
弧线移动(抛物线轨迹)
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': 60},
start_pos=(50, 350),
end_pos=(430, 350),
motion_type='arc',
motion_params={'arc_height': 150}
)
Circular movement
圆周移动
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 # full circle
}
)
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 # 完整圆周
}
)
Wave movement
波浪移动
frames = create_move_animation(
motion_type='wave',
motion_params={
'wave_amplitude': 50,
'wave_frequency': 2
}
)
frames = create_move_animation(
motion_type='wave',
motion_params={
'wave_amplitude': 50,
'wave_frequency': 2
}
)
Or use low-level easing functions
或使用底层缓动函数
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')
# Or: x, y = calculate_arc_motion(start, end, height, t)
undefinedfrom 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')
# 或:x, y = calculate_arc_motion(start, end, height, t)
undefinedKaleidoscope Effect
万花筒效果
python
from templates.kaleidoscope import apply_kaleidoscope, create_kaleidoscope_animationpython
from templates.kaleidoscope import apply_kaleidoscope, create_kaleidoscope_animationApply to a single frame
应用到单帧
kaleido_frame = apply_kaleidoscope(frame, segments=8)
kaleido_frame = apply_kaleidoscope(frame, segments=8)
Or create animated kaleidoscope
或创建万花筒动画
frames = create_kaleidoscope_animation(
base_frame=my_frame, # or None for demo pattern
num_frames=30,
segments=8,
rotation_speed=1.0
)
frames = create_kaleidoscope_animation(
base_frame=my_frame, # 或传入None使用演示图案
num_frames=30,
segments=8,
rotation_speed=1.0
)
Simple mirror effects (faster)
简单镜像效果(速度更快)
from templates.kaleidoscope import apply_simple_mirror
mirrored = apply_simple_mirror(frame, mode='quad') # 4-way mirror
from templates.kaleidoscope import apply_simple_mirror
mirrored = apply_simple_mirror(frame, mode='quad') # 4向镜像
modes: 'horizontal', 'vertical', 'quad', 'radial'
模式可选:'horizontal'(水平), 'vertical'(垂直), 'quad'(四向), 'radial'(径向)
**To compose primitives freely, follow these patterns:**
```python
**如需自由组合基础组件,请遵循以下模式:**
```pythonExample: Bounce + shake for impact
示例:弹跳+摇晃增强冲击力
for i in range(num_frames):
frame = create_blank_frame(480, 480, bg_color)
# Bounce motion
t_bounce = i / (num_frames - 1)
y = interpolate(start_y, ground_y, t_bounce, 'bounce_out')
# Add shake on impact (when y reaches ground)
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)undefinedfor 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')
# 触地时添加摇晃(当y接近地面时)
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)undefinedHelper Utilities
辅助工具
These are optional helpers for common needs. Use, modify, or replace these with custom implementations as needed.
这些是满足常见需求的可选工具。可根据需要使用、修改或替换为自定义实现。
GIF Builder (Assembly & Optimization)
GIF构建器(组装与优化)
python
from core.gif_builder import GIFBuilderpython
from core.gif_builder import GIFBuilderCreate builder with your chosen settings
使用自定义设置创建构建器
builder = GIFBuilder(width=480, height=480, fps=20)
builder = GIFBuilder(width=480, height=480, fps=20)
Add frames (however you created them)
添加帧(无论你如何创建的帧)
for frame in my_frames:
builder.add_frame(frame)
for frame in my_frames:
builder.add_frame(frame)
Save with optimization
带优化保存
builder.save('output.gif',
num_colors=128,
optimize_for_emoji=False)
Key features:
- Automatic color quantization
- Duplicate frame removal
- Size warnings for Slack limits
- Emoji mode (aggressive optimization)builder.save('output.gif',
num_colors=128,
optimize_for_emoji=False)
核心特性:
- 自动颜色量化
- 重复帧移除
- Slack大小限制警告
- 表情模式(深度优化)Text Rendering
文本渲染
For small GIFs like emojis, text readability is challenging. A common solution involves adding outlines:
python
from core.typography import draw_text_with_outline, TYPOGRAPHY_SCALE对于表情动图这类小尺寸GIF,文本可读性是一大挑战。常用解决方案是添加轮廓:
python
from core.typography import draw_text_with_outline, TYPOGRAPHY_SCALEText with outline (helps readability)
带轮廓的文本(提升可读性)
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
)
To implement custom text rendering, use PIL's `ImageDraw.text()` which works fine for larger GIFs.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
)
如需实现自定义文本渲染,可使用PIL的`ImageDraw.text()`,它在大尺寸GIF上表现良好。Color Management
颜色管理
Professional-looking GIFs often use cohesive color palettes:
python
from core.color_palettes import get_palette专业的GIF通常使用协调的调色板:
python
from core.color_palettes import get_paletteGet a pre-made palette
获取预制调色板
palette = get_palette('vibrant') # or 'pastel', 'dark', 'neon', 'professional'
bg_color = palette['background']
text_color = palette['primary']
accent_color = palette['accent']
To work with colors directly, use RGB tuples - whatever works for the use case.palette = get_palette('vibrant') # 可选:'pastel'(马卡龙), 'dark'(深色), 'neon'(霓虹), 'professional'(专业)
bg_color = palette['background']
text_color = palette['primary']
accent_color = palette['accent']
如需直接操作颜色,可使用RGB元组——根据需求选择即可。Visual Effects
视觉特效
Optional effects for impact moments:
python
from core.visual_effects import ParticleSystem, create_impact_flash, create_shockwave_rings用于增强冲击力的可选特效:
python
from core.visual_effects import ParticleSystem, create_impact_flash, create_shockwave_ringsParticle system
粒子系统
particles = ParticleSystem()
particles.emit_sparkles(x=240, y=200, count=15)
particles.emit_confetti(x=240, y=200, count=20)
particles = ParticleSystem()
particles.emit_sparkles(x=240, y=200, count=15)
particles.emit_confetti(x=240, y=200, count=20)
Update and render each frame
更新并渲染每帧
particles.update()
particles.render(frame)
particles.update()
particles.render(frame)
Flash effect
闪光效果
frame = create_impact_flash(frame, position=(240, 200), radius=100)
frame = create_impact_flash(frame, position=(240, 200), radius=100)
Shockwave rings
冲击波环
frame = create_shockwave_rings(frame, position=(240, 200), radii=[30, 60, 90])
undefinedframe = create_shockwave_rings(frame, position=(240, 200), radii=[30, 60, 90])
undefinedEasing Functions
缓动函数
Smooth motion uses easing instead of linear interpolation:
python
from core.easing import interpolate平滑运动需使用缓动而非线性插值:
python
from core.easing import interpolateObject falling (accelerates)
物体下落(加速)
y = interpolate(start=0, end=400, t=progress, easing='ease_in')
y = interpolate(start=0, end=400, t=progress, easing='ease_in')
Object landing (decelerates)
物体落地(减速)
y = interpolate(start=0, end=400, t=progress, easing='ease_out')
y = interpolate(start=0, end=400, t=progress, easing='ease_out')
Bouncing
弹跳
y = interpolate(start=0, end=400, t=progress, easing='bounce_out')
y = interpolate(start=0, end=400, t=progress, easing='bounce_out')
Overshoot (elastic)
过冲(弹性)
scale = interpolate(start=0.5, end=1.0, t=progress, easing='elastic_out')
Available easings: `linear`, `ease_in`, `ease_out`, `ease_in_out`, `bounce_out`, `elastic_out`, `back_out` (overshoot), and more in `core/easing.py`.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`。Frame Composition
帧合成
Basic drawing utilities if you need them:
python
from core.frame_composer import (
create_gradient_background, # Gradient backgrounds
draw_emoji_enhanced, # Emoji with optional shadow
draw_circle_with_shadow, # Shapes with depth
draw_star # 5-pointed stars
)如需基础绘图工具,可使用以下工具:
python
from core.frame_composer import (
create_gradient_background, # 渐变背景
draw_emoji_enhanced, # 带可选阴影的表情
draw_circle_with_shadow, # 带深度的形状
draw_star # 五角星
)Gradient background
渐变背景
frame = create_gradient_background(480, 480, top_color, bottom_color)
frame = create_gradient_background(480, 480, top_color, bottom_color)
Emoji with shadow
带阴影的表情
draw_emoji_enhanced(frame, '🎉', position=(200, 200), size=80, shadow=True)
undefineddraw_emoji_enhanced(frame, '🎉', position=(200, 200), size=80, shadow=True)
undefinedOptimization Strategies
优化策略
When your GIF is too large:
For Message GIFs (>2MB):
- Reduce frames (lower FPS or shorter duration)
- Reduce colors (128 → 64 colors)
- Reduce dimensions (480x480 → 320x320)
- Enable duplicate frame removal
For Emoji GIFs (>64KB) - be aggressive:
- Limit to 10-12 frames total
- Use 32-40 colors maximum
- Avoid gradients (solid colors compress better)
- Simplify design (fewer elements)
- Use in save method
optimize_for_emoji=True
当GIF文件过大时:
消息动图(>2MB):
- 减少帧数(降低帧率或缩短时长)
- 减少颜色(从128色→64色)
- 缩小尺寸(从480x480→320x320)
- 启用重复帧移除
表情动图(>64KB)——需激进优化:
- 总帧数限制在10-12帧
- 最多使用32-40种颜色
- 避免渐变(纯色压缩效果更好)
- 简化设计(减少元素)
- 保存时使用参数
optimize_for_emoji=True
Example Composition Patterns
示例组合模式
Simple Reaction (Pulsing)
简单反应动图(脉冲)
python
builder = GIFBuilder(128, 128, 10)
for i in range(12):
frame = Image.new('RGB', (128, 128), (240, 248, 255))
# Pulsing scale
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)python
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)Validate
验证
from core.validators import check_slack_size
check_slack_size('reaction.gif', is_emoji=True)
undefinedfrom core.validators import check_slack_size
check_slack_size('reaction.gif', is_emoji=True)
undefinedAction with Impact (Bounce + Flash)
带冲击力的动作(弹跳+闪光)
python
builder = GIFBuilder(480, 480, 20)python
builder = GIFBuilder(480, 480, 20)Phase 1: Object falls
阶段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)
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)
Phase 2: Impact + flash
阶段2:撞击+闪光
for i in range(8):
frame = create_gradient_background(480, 480, (240, 248, 255), (200, 230, 255))
# Flash on first frames
if i < 3:
frame = create_impact_flash(frame, (240, 350), radius=120, intensity=0.6)
draw_emoji_enhanced(frame, '⚽', position=(220, 350), size=80)
# Text appears
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)
undefinedfor 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)
undefinedCombining Primitives (Move + Shake)
组合基础组件(移动+摇晃)
python
from templates.shake import create_shake_animationpython
from templates.shake import create_shake_animationCreate shake animation
创建摇晃动画
shake_frames = create_shake_animation(
object_type='emoji',
object_data={'emoji': '😰', 'size': 70},
num_frames=20,
shake_intensity=12
)
shake_frames = create_shake_animation(
object_type='emoji',
object_data={'emoji': '😰', 'size': 70},
num_frames=20,
shake_intensity=12
)
Create moving element that triggers the shake
创建触发摇晃的移动元素
builder = GIFBuilder(480, 480, 20)
for i in range(40):
t = i / 39
if i < 20:
# Before trigger - use blank frame with moving object
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:
# After trigger - use shake frame
frame = shake_frames[i - 20]
# Add the car in final position
draw_emoji_enhanced(frame, '🚗', position=(300, 300), size=60)
builder.add_frame(frame)builder.save('scare.gif')
undefinedbuilder = 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')
undefinedPhilosophy
设计理念
This toolkit provides building blocks, not rigid recipes. To work with a GIF request:
- Understand the creative vision - What should happen? What's the mood?
- Design the animation - Break it into phases (anticipation, action, reaction)
- Apply primitives as needed - Shake, bounce, move, effects - mix freely
- Validate constraints - Check file size, especially for emoji GIFs
- Iterate if needed - Reduce frames/colors if over size limits
The goal is creative freedom within Slack's technical constraints.
本工具包提供构建模块,而非固定模板。处理GIF请求时请遵循以下步骤:
- 理解创意需求 - 要呈现什么内容?氛围如何?
- 设计动画 - 将动画拆分为多个阶段(铺垫、动作、反应)
- 按需应用基础组件 - 摇晃、弹跳、移动、特效——自由组合
- 验证约束 - 检查文件大小,尤其是表情动图
- 按需迭代 - 若超出大小限制,减少帧数/颜色
目标是在Slack的技术约束内实现创意自由。
Dependencies
依赖项
To use this toolkit, install these dependencies only if they aren't already present:
bash
pip install pillow imageio numpy如需使用本工具包,若尚未安装以下依赖项,请执行安装:
bash
pip install pillow imageio numpy