Preface
Recently, when uploading pictures in the background of the blog, I suddenly found that there was a problem with cropping pictures when uploading gif pictures. It is impossible to crop the picture in the specified area of the gif, and it is impossible to crop the specified area to generate a new gif image of the specified size. Originally intended to go directly to a cutting library directly put up, but look for a long time can not find cut and then generate gif gif crop area of library, so he do it yourself.
explore
If you simply crop the first frame of the picture on the Gif, there are plug-ins that can do it. I use react- to crop the picture. But this plug-in cannot crop the GIF to generate another GIF image.
The effect I want is the following effect
Original image
Cropped gif
Then I checked how to cut the gif image to the gif image. Although I didn't find the corresponding plug-in, I found two open source libraries.
I found that a combination of these two functions can achieve the effect I want.
Upload GIF => Generate a corresponding image on Canvas by parsing each frame of GIF => Convert canvas to GIF
achieve
The realization process of libgif-js
libgif-js
is to initiate a request to the gif path, and then generate a GIF instance (including the animation of each frame, and basic data such as size) by parsing the gif data returned by the request, and then generate the corresponding canvas
The realization process of gif.js
GIF
is generated by collecting the changes of each frame of libgif-js
converted to the canvas.
The realization process of converting gif to canvas
First, download the corresponding js file in the libgif-js project, because this library does not upload npm, so you need to download it in the project yourself.libgif-js
He encapsulates the HTML
node, which cannot be used directly, because I uploaded a file and obtained the File
object, so I need to modify this file partially
- The first thing that should be received is a
url
path. You can convert theFile file to
URL.createObjectURL(file)
url
, and let it make aXMLHttpRequest
request. You can also directly pass the link ofgif
- Then you need to pass the cropped area. The size of the cropping range needs to be adapted to the size ratio of the original gif
- Remove the
libgif-js
file, and only need the image collection and size of each frame.
The realization process of canvas to gif
Monitor every frame change of the gif drawn on the canvas, then gif.js
collects the canvas change of each frame, and finally generate a new 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)
...
})
This generates a cropped gif file.
Reference Resources
The complete code of this project: GitHub repository
to sum up
This project did not do too many complicated settings, just to meet the function of cropping GIF, because I only need to crop the gif to a gif of a specified size at present, so there are not too many special functions.
Personal blog source code project also launched this function | blog source code project address
I have created a new group to learn from each other. Whether you are a Xiaobai who is about to enter the pit, or a classmate who is halfway into the industry, I hope we can share and communicate together.
QQ group: 810018802, click to join
QQ group | the public |
---|---|
Front end miscellaneous group | Winter Melon Bookstore |
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。