js 实现gif
使用 Canvas 生成 GIF
通过 canvas 绘制帧并利用 gif.js 或 omggif 库编码为 GIF 格式。

// 安装 gif.js
// npm install gif.js
import GIF from 'gif.js';
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const gif = new GIF({
workers: 2,
quality: 10,
width: canvas.width,
height: canvas.height
});
// 添加帧(示例:绘制矩形动画)
for (let i = 0; i < 10; i++) {
ctx.fillStyle = `rgb(${i * 25}, 0, 0)`;
ctx.fillRect(0, 0, 100, 100);
gif.addFrame(canvas, { delay: 100, copy: true });
}
// 生成 GIF
gif.on('finished', (blob) => {
const url = URL.createObjectURL(blob);
const img = document.createElement('img');
img.src = url;
document.body.appendChild(img);
});
gif.render();
使用 FFmpeg.js 转换视频为 GIF
通过 ffmpeg.js 将视频或图像序列转为 GIF(适用于复杂场景)。

// 安装 FFmpeg.js
// npm install @ffmpeg/ffmpeg @ffmpeg/core
import { createFFmpeg, fetchFile } from '@ffmpeg/ffmpeg';
const ffmpeg = createFFmpeg({ log: true });
await ffmpeg.load();
// 假设已有视频文件
const videoData = await fetchFile('input.mp4');
ffmpeg.FS('writeFile', 'input.mp4', videoData);
// 转换为 GIF
await ffmpeg.run('-i', 'input.mp4', '-vf', 'fps=10', 'output.gif');
const gifData = ffmpeg.FS('readFile', 'output.gif');
const gifUrl = URL.createObjectURL(new Blob([gifData.buffer], { type: 'image/gif' }));
document.getElementById('gif').src = gifUrl;
使用纯前端库 gifencoder
通过 gifencoder 直接生成 GIF,适合动态绘图场景。
// 安装 gifencoder
// npm install gifencoder
const { createCanvas } = require('canvas');
const GIFEncoder = require('gifencoder');
const encoder = new GIFEncoder(200, 200);
encoder.createReadStream().pipe(fs.createWriteStream('output.gif'));
encoder.start();
encoder.setRepeat(0); // 0 为无限循环
encoder.setDelay(100); // 帧延迟(毫秒)
const canvas = createCanvas(200, 200);
const ctx = canvas.getContext('2d');
for (let i = 0; i < 10; i++) {
ctx.fillStyle = `rgb(${i * 25}, 0, 0)`;
ctx.fillRect(0, 0, 200, 200);
encoder.addFrame(ctx);
}
encoder.finish();
注意事项
- 性能问题:GIF 编码较耗时,建议在 Web Worker 中处理。
- 质量与体积:调整
quality和fps以平衡清晰度和文件大小。 - 兼容性:
gif.js和ffmpeg.js需现代浏览器支持。
以上方法可根据需求选择,canvas + gif.js 适合简单动画,ffmpeg.js 适合复杂媒体转换。






