基础原理
- gif库:用于生成gif动图
- video转gif原理:
- 设置时间函数
setInterval()、通过canvas截取video元素固定时间间隔的帧画面 - 调用
gif.addFrame(),将截取画面作为 gif 中的一帧追加到gif图中 - 监听视频播放完毕的
onended事件,调用gif.render()完成对gif添加帧的渲染 - 监听
gif.on('finished', function(blob){})将blob转为可下载链接并下载到本地
- 设置时间函数
划重点:由于这里是通过固定时间间隔,截图视频帧画面来生成GIF图,所以需要让视频自然播放直到结束。(当然你也可以设置video倍速播放)
gif.js 基础api
var gif = new GIF({
quality: 10, // gif 清晰度,越低越清晰
workerScript: './gif.worker.js', // 借助worker运行video解决视频跨域问题
debug: true // 开启调试模式
});
// 将canvas节点追加到gif帧中,delay 是每一帧的时间间隔
gif.addFrame(canvasElement, {delay: 200});
// 监听渲染完成,返回 blob 文件流
gif.on('finished', function(blob) {
const url = URL.createObjectURL(blob);
});
// 将每一帧渲染成一张完成的gif
gif.render();
逻辑代码
// 本地上传视频文件,生成视频url
input.addEventListener('change', () => {
const videoFile = e.target.files[0];
const videoUrl = URL.createObjectURL(videoFile)
video.setAttribute('src', videoUrl);
})
// 创建GIF
const videoGif = new GIF({
workers: 2,
quality: 1,
workerScript: './gif.worker.js',
debug: true
});
// 设定时间间隔
const delay = 100;
// video 事件监听与播放
video.addEventListener('loadedmetadata', () => {
// 部分视频尺寸可能会很大,可以再加载完成时设置样式缩小其尺寸
const width = this.video.videoWidth / 5;
const height = this.video.videoHeight / 5;
video.setAttribute('style', `width:${width}px;height:${height}px`);
})
video.addEventListener('ended' = () => {
// 视频播放完毕,清除时间函数
clearInterval(timer);
// 将追加的gif帧,渲染成完整图
videoGif.render()
// 监听渲染完毕,并输出 gif 地址
videoGif.on('finished', blob => {
const gifImg = URL.createObjectURL(blob);
})
})
video.play(); // 播放视频
// 创建canvas
const canvas = document.createElement("canvas");
const ctx = canvas.getContext('2d');
// 设置时间函数
const timer = setInterval(() => {
// 画布的宽高与视频宽高保持一致,延迟取上面定义的延迟时间
canvas.width = width;
canvas.height = height;
canvas.delay = delay
canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);
// 将当前画面帧追加到 gif中
const imgImage = new Image();
imgImage.src = canvas.toDataURL("image/png");
imgImage.onload = (e) => {
// 绘制底色
ctx.fillRect(0, 0, canvas.width, canvas.height);
// 绘制当前帧
ctx.drawImage(imgImage, 0, 0, canvas.width, canvas.height);
// 当前帧追加到gif中
gif.addFrame(canvas, {copy: true, delay: canvas.delay});
}
}, delay)
// 下载转换后的gif图
download.addEventListener('click', () => {
const aLink = document.createElement('a');
aLink.setAttribute('download', 'img')
aLink.setAttribute('href', gifImg)
aLink.click()
})