Slack GIF 製作工具 是做什麼的?
一個提供工具與知識的工具包,用於建立適用於 Slack 的最佳化動態 GIF。
Slack 限制規格
尺寸:
- Emoji GIF:128x128(建議)
- 訊息 GIF:480x480
參數:
- FPS:10-30(較低值 = 檔案較小)
- 色彩數:48-128(越少 = 檔案越小)
- 時長:Emoji GIF 請控制在 3 秒以下
核心工作流程
from core.gif_builder import GIFBuilder
from PIL import Image, ImageDraw
# 1. 建立建構器
builder = GIFBuilder(width=128, height=128, fps=10)
# 2. 產生影格
for i in range(12):
frame = Image.new('RGB', (128, 128), (240, 248, 255))
draw = ImageDraw.Draw(frame)
# 使用 PIL 基本圖形繪製動畫
# (圓形、多邊形、線條等)
builder.add_frame(frame)
# 3. 儲存並最佳化
builder.save('output.gif', num_colors=48, optimize_for_emoji=True)
繪製圖形
處理使用者上傳的圖片
如果使用者上傳了一張圖片,請考慮他們想要:
- 直接使用該圖片(例如:「將此圖片做成動畫」、「將這個拆成多個影格」)
- 以該圖片為靈感(例如:「做一個類似的東西」)
使用 PIL 載入並處理圖片:
from PIL import Image
uploaded = Image.open('file.png')
# 直接使用,或僅作為顏色/風格的參考
從頭繪製圖形
從頭開始繪製圖形時,使用 PIL ImageDraw 基本圖形:
from PIL import ImageDraw
draw = ImageDraw.Draw(frame)
# 圓形/橢圓
draw.ellipse([x1, y1, x2, y2], fill=(r, g, b), outline=(r, g, b), width=3)
# 星形、三角形、任意多邊形
points = [(x1, y1), (x2, y2), (x3, y3), ...]
draw.polygon(points, fill=(r, g, b), outline=(r, g, b), width=3)
# 線條
draw.line([(x1, y1), (x2, y2)], fill=(r, g, b), width=5)
# 矩形
draw.rectangle([x1, y1, x2, y2], fill=(r, g, b), outline=(r, g, b), width=3)
請勿使用: Emoji 字型(跨平台不可靠)或假設此技能內建預製圖形。
讓圖形看起來更美觀
圖形應看起來精緻且有創意,而非簡單粗糙。以下是作法:
使用較粗的線條 - 一律將外框與線條的 width 設定為 2 或更高。細線條(width=1)看起來粗糙不專業。
增加視覺深度:
- 使用漸層背景(
create_gradient_background) - 疊加多個形狀以增加複雜度(例如:大星星內包含小星星)
讓形狀更有趣:
- 不要只是畫一個單純的圓形 - 加上高光、環狀或圖案
- 星星可以加上光暈(在後面繪製較大、半透明的版本)
- 組合多個形狀(星星 + 閃光、圓形 + 環)
注意顏色:
- 使用鮮豔、互補的顏色
- 增加對比(深色外框配淺色形狀,淺色外框配深色形狀)
- 考慮整體構圖
對於複雜形狀(愛心、雪花等):
- 使用多邊形與橢圓的組合
- 仔細計算點的位置以保持對稱
- 加入細節(愛心可以有高光曲線,雪花有複雜的分支)
請發揮創意與細節!一個好的 Slack GIF 應該看起來精緻,而不是像預設圖形。
可用的工具函式
GIFBuilder(core.gif_builder)
組裝影格並針對 Slack 最佳化:
builder = GIFBuilder(width=128, height=128, fps=10)
builder.add_frame(frame) # 加入 PIL Image
builder.add_frames(frames) # 加入影格列表
builder.save('out.gif', num_colors=48, optimize_for_emoji=True, remove_duplicates=True)
驗證器(core.validators)
檢查 GIF 是否符合 Slack 需求:
from core.validators import validate_gif, is_slack_ready
# 詳細驗證
passes, info = validate_gif('my.gif', is_emoji=True, verbose=True)
# 快速檢查
if is_slack_ready('my.gif'):
print("準備就緒!")
緩動函數(core.easing)
實現平順的動畫,而非線性移動:
from core.easing import interpolate
# 進度從 0.0 到 1.0
t = i / (num_frames - 1)
# 套用緩動
y = interpolate(start=0, end=400, t=t, easing='ease_out')
# 可用的緩動:linear, ease_in, ease_out, ease_in_out,
# bounce_out, elastic_out, back_out
影格輔助函式(core.frame_composer)
常用功能的便利函式:
from core.frame_composer import (
create_blank_frame, # 純色背景
create_gradient_background, # 垂直漸層
draw_circle, # 繪製圓形的輔助函式
draw_text, # 簡單文字渲染
draw_star # 五角星
)
動畫概念
抖動/震動
透過震盪讓物體位置偏移:
- 使用
math.sin()或math.cos()搭配影格索引 - 加入小的隨機變化以產生自然感
- 套用至 x 或 y 位置
脈衝/心跳
有節奏地縮放物體大小:
- 使用
math.sin(t * frequency * 2 * math.pi)實現平順脈衝 - 心跳:兩次快速脈衝後暫停(調整正弦波)
- 在基礎大小的 0.8 到 1.2 之間縮放
彈跳
物體落下並彈跳:
- 使用
interpolate()搭配easing='bounce_out'實現落地 - 使用
easing='ease_in'實現落下(加速) - 每個影格增加 y 速度以模擬重力
旋轉
繞中心旋轉物體:
- PIL:
image.rotate(angle, resample=Image.BICUBIC) - 晃動效果:使用正弦波控制角度,而非線性
淡入/淡出
逐漸出現或消失:
- 建立 RGBA 圖片,調整 Alpha 通道
- 或使用
Image.blend(image1, image2, alpha) - 淡入:alpha 從 0 到 1
- 淡出:alpha 從 1 到 0
滑入
將物體從畫面外移至指定位置:
- 起始位置:畫面範圍外
- 結束位置:目標位置
- 使用
interpolate()搭配easing='ease_out'產生平順停止 - 若要產生過衝效果:使用
easing='back_out'
縮放
透過縮放與位置變化實現縮放效果:
- 放大:從 0.1 倍縮放到 2.0 倍,裁切中心
- 縮小:從 2.0 倍縮放到 1.0 倍
- 可以加入動態模糊增加戲劇效果(PIL 濾鏡)
爆炸/粒子爆發
產生向外輻射的粒子:
- 以隨機角度與速度產生粒子
- 更新每個粒子:
x += vx,y += vy - 加入重力:
vy += gravity_constant - 隨時間淡化粒子(減少 alpha)
最佳化策略
只有在被要求縮小檔案大小時,才實作以下部分方法:
- 減少影格數 - 降低 FPS(10 而非 20)或縮短時長
- 減少色彩數 -
num_colors=48而非 128 - 縮小尺寸 - 128x128 而非 480x480
- 移除重複影格 -
remove_duplicates=True在 save() 中 - Emoji 模式 -
optimize_for_emoji=True自動最佳化
# Emoji 最大最佳化
builder.save(
'emoji.gif',
num_colors=48,
optimize_for_emoji=True,
remove_duplicates=True
)
哲學
此技能提供:
- 知識:Slack 的限制規格與動畫概念
- 工具:GIFBuilder、驗證器、緩動函數
- 靈活性:使用 PIL 基本圖形建立動畫邏輯
此技能不提供:
- 固定的動畫模板或預製函式
- Emoji 字型渲染(跨平台不可靠)
- 內建於技能中的預製圖形庫
關於使用者上傳的圖片:此技能不包含預製圖形,但如果使用者上傳了圖片,請使用 PIL 載入並處理 - 根據他們的要求判斷是要直接使用還是僅作為靈感。
請發揮創意!結合不同概念(彈跳 + 旋轉、脈衝 + 滑入等),並善用 PIL 的完整功能。
相依套件
pip install pillow imageio numpy