用於建立最佳化 Slack 動態 GIF 的工具包,包含大小限制驗證器與可組合的動畫基本元件。當使用者要求從描述(例如「幫我做一個 X 做 Y 的 Slack GIF」)建立動態 GIF 或表情動畫時,適用此技能。
Slack GIF Creator - 彈性工具包
用於建立最佳化 Slack 的動態 GIF 工具包。提供 Slack 限制驗證器、可組合的動畫基本元件,以及選用的輔助工具。請根據創意需求自由運用這些工具。
Slack 的要求
Slack 對 GIF 有特定要求,依用途區分:
訊息 GIF:
- 最大大小:約 2MB
- 最佳尺寸:480x480
- 典型 FPS:15-20
- 顏色數:128-256
- 持續時間:2-5 秒
表情 GIF:
- 最大大小:64KB(嚴格限制)
- 最佳尺寸:128x128
- 典型 FPS:10-12
- 顏色數:32-48
- 持續時間:1-2 秒
表情 GIF 具有挑戰性 - 64KB 限制很嚴格。有幫助的策略:
- 限制總幀數為 10-15 幀
- 最多使用 32-48 種顏色
- 保持設計簡單
- 避免漸層
- 頻繁驗證檔案大小
工具包結構
此技能提供三種工具:
- 驗證器 - 檢查 GIF 是否符合 Slack 要求
- 動畫基本元件 - 可組合的動作建構區塊(搖晃、彈跳、移動、萬花筒)
- 輔助工具 - 常用功能的選用函式(文字、顏色、特效)
這些工具的應用方式完全自由。
核心驗證器
為確保 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("可以上傳!")
動畫基本元件
這些是可組合的動作建構區塊。可將這些應用於任何物件,任意組合:
搖晃
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' # 或 'horizontal', 'vertical'
)
彈跳
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
)
旋轉
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')
脈衝 / 心跳
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)
淡入淡出
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}
)
縮放
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='💥')
爆炸 / 碎裂
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)
扭動 / 抖動
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='🎉')
滑入
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)
翻轉
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')
# 表情 GIF 的快速翻轉
frames = create_quick_flip('👍', '👎')
變形 / 轉換
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')
移動效果
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')
# 或:x, y = calculate_arc_motion(start, end, height, t)
萬花筒效果
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') # 四向鏡像
# modes: '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')
# 撞擊時加入搖晃(當 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)
輔助工具
這些是常用功能的選用輔助工具。可根據需要自行使用、修改或取代。
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
)
若要實作自訂文字渲染,可使用 PIL 的 ImageDraw.text(),這在較大的 GIF 中運作良好。
色彩管理
專業外觀的 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']
若要直接使用顏色,可使用 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 太大時:
對於訊息 GIF(>2MB):
- 減少幀數(降低 FPS 或縮短持續時間)
- 減少顏色數(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)
組合基本元件(移動 + 搖晃)
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 請求時:
- 理解創意願景 - 應該發生什麼?情緒是什麼?
- 設計動畫 - 分解為階段(預期、動作、反應)
- 按需應用基本元件 - 搖晃、彈跳、移動、效果 - 自由混合
- 驗證限制 - 檢查檔案大小,尤其是表情 GIF
- 必要時迭代 - 若超過大小限制,減少幀數/顏色
目標是在 Slack 的技術限制內實現創意自由。
相依套件
若要使用此工具包,僅在尚未安裝時安裝這些相依套件:
pip install pillow imageio numpy






