前言
最近在博客后盾上传图片的时候,忽然发现上传gif图片的时候裁剪图片有问题。既没法裁剪gif指定区域的图片,又没法裁剪指定区域生成一个新的指定大小的gif图。原本想间接去找个裁剪的库间接放上去的,然而找了半天也没找到可能裁剪gif而后生成裁剪区域的gif的库,于是就本人入手了。
摸索
如果只是单纯的在Gif上裁剪第一帧图片,倒是有插件能实现,我用的就是react-cropper来进行图片裁剪的。然而这个插件没法裁剪GIF生成另一个GIF图。
我要的成果是上面这样的成果
原图
裁剪后的gif图
而后就去查了下如何实现gif图到gif图的裁剪,尽管没有找到对应的插件,然而找到了两个开源的库。
- libgif-js 通过解析GIF,生成Canvas
- gif.js 把canvas转换成GIF图片
发现这两个性能一组合不就能够实现我要的那个成果了么。
上传GIF => 通过解析GIF每一帧在Canvas上生成对应的图像 => canvas转成GIF
实现
libgif-js的实现过程
libgif-js
是通过实现对gif门路发动一个申请,而后通过解析申请回来的gif数据来生成GIF实例(包含每一帧的动画,以及大小之类的根底数据),而后通过GIF实例生成对应的canvas
gif.js的实现过程
通过收集libgif-js
转换到canvas下面的每一帧的变动,来生成最终的GIF
。
gif转换到canvas的实现过程
首先到libgif-js这个我的项目中下载对应的js文件,因为这个库并没有上传npm,所以须要本人去我的项目中下载。libgif-js
他这个封装的是对HTML
节点的操作,没法间接去用,因为我是上传文件,获取的File
对象,所以须要对这个文件进行局部批改
- 首先应该接管的是一个
url
门路,能够把File文件
通过URL.createObjectURL(file)
转成成url
,让其进行XMLHttpRequest
申请。 也能够间接传gif
的链接。 - 而后须要传裁剪的区域范畴。裁剪的范畴大小须要适配原gif的尺寸比例
- 去除
libgif-js
文件外面不须要的代码,只须要其中每一帧的图像汇合跟尺寸大小就行
canvas转换到gif的实现过程
监听gif绘制到canvas上的每一帧变动,而后gif.js
收集每一帧的canvas变动,最初生成新的gif
// 导出gif实例, GifToCanvas实例是对libgif-js封装的批改,通过调用init办法,触发gif到canvas的绘制
const gifToCanvas = new GifToCanvas(url, {
targetOffset: {
dx: cropBoxData.left - canvasData.left,
dy: cropBoxData.top - canvasData.top,
width: canvasData.width,
height: canvasData.height,
sWidth: cropBoxData.width,
sHeight: cropBoxData.height
}
})
// 启动gif转canvas
gifToCanvas.init()
// 通过 gif.js 库来收集由 GifToCanvas绘制进去的canvas外面的每一帧,最初生成gif的Blob源。
const gif = new GIF({
workers: 2,
quality: 10,
workerScript: '/static/js/gif.worker.js'
})
const addFrame = (canvas: HTMLCanvasElement, delay: number) => {
gif.addFrame(canvas, { copy: true, delay })
}
// 监听每一帧的变动,收集每一帧的变动
gifToCanvas.on('progress', (canvas, delay) => {
addFrame(canvas, delay)
})
// 动画执行结束,执行gif.render
gifToCanvas.on('finished', (canvas, delay) => {
addFrame(canvas, delay)
gif.render()
})
// canvas生成gif结束,导出blob, 生成新的文件
gif.on('finished', (blob) => {
const newFile = new File([blob], 'new.gif', { type: blob.type })
// 上传新的gif文件
const formDate = new FormData()
formDate.append('file', newFile)
...
})
这样就生成了一个裁剪后的gif文件。
参考资源
- libgif-js
- gif.js
本我的项目残缺的代码:GitHub 仓库
线上成果演示
博客原文地址
总结
这个我的项目也没有做太多简单的设置,满足裁剪GIF的性能就行,因为我目前只须要把gif裁剪成指定大小的gif就行,所以并没有做太多特制化的性能
集体博客源码这个我的项目也上线了这个性能 | 博客源码我的项目地址
我本人新创建了一个互相学习的群,无论你是筹备入坑的小白,还是半路入行的同学,心愿咱们能一起分享与交换。
QQ群:810018802, 点击退出
QQ群 | 公众号 |
---|---|
前端打杂群 |
冬瓜书屋 |
发表回复