preface

Recently I was uploading pictures in the background of my blog, and suddenly I found a problem with cropping images when uploading GIF images. There is no way to crop the GIF image for the specified area, or crop the specified area to generate a new GIF of the specified size. I wanted to find a clipping library to put directly, but after searching for a long time, I couldn’t find a library that could crop giFs and then generate the clipping area, so I did it myself.

explore

If you’re just cropping the first frame on a Gif, there’s a plugin for that. I used React-Cropper for cropping. But the plugin can’t crop a GIF to generate another GIF.

What I want is something like this

The original image

Cropped GIF

Then I went to look up how to achieve the cutting of GIF images to GIF images. Although I did not find the corresponding plug-in, I found two open source libraries.

  1. Libgif-js parses giFs to generate Canvas
  2. GIF. Js converts canvas into GIF images

I found that the combination of these two functions can not achieve the effect I want.

Upload GIF => Generate the corresponding image on Canvas by parsing each frame of GIF => Canvas into GIF

implementation

Libgif-js implementation process

Libgif-js is an implementation that makes a request to the GIF path, parses the requested GIF data to generate a GIF instance (including the animation of each frame, as well as basic data such as the size), and then generates the corresponding canvas from the GIF instance

GIF. Js implementation process

Generate the final GIF by collecting the changes of each frame converted from libgif-js to the canvas.

GIF conversion to Canvas implementation process

Download the libgif-js js file from the libgif-js project. Since this library does not upload NPM, you will need to download it from the project. Libgif-js encapsulates operations on HTML nodes and cannot be used directly, because I uploaded the File and obtained the File object, so I need to modify the File partially

  1. The first thing you should receive is aurlPath, you can takeThe File FilethroughURL.createObjectURL(file)Convert intourlLet it happenXMLHttpRequestThe request. You can also send it directlygifThe link.
  2. Then you need to pass the clipped range. The cropped range size needs to be proportional to the size of the original GIF
  3. Get rid oflibgif-jsFile inside do not need the code, just need each frame of the image set and size on the line

Canvas conversion to GIF implementation process

Listen for each frame change that the GIF draws to the canvas, and then gif.js collects the canvas change of each frame and generates a new GIF

The GifToCanvas instance is a modification of the libgif-js wrapper, which triggers the GIF to canvas drawing by calling init
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
  }
})
// Start GIF to canvas
gifToCanvas.init()

// Collect each frame of canvas drawn by GifToCanvas through gif.js library, and finally generate GIF Blob source.
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 })
}
// Listen to each frame change, collect each frame change
gifToCanvas.on('progress'.(canvas, delay) = > {
  addFrame(canvas, delay)
})
// When the animation is finished, execute GIF. Render
gifToCanvas.on('finished'.(canvas, delay) = > {
  addFrame(canvas, delay)
  gif.render()
})
// After canvas generates GIF, export blob and generate new file
gif.on('finished'.(blob) = > {
  const newFile = new File([blob], 'new.gif', { type: blob.type })
  // Upload a new GIF file
  const formDate = new FormData()
  formDate.append('file', newFile)
  ...
})
Copy the code

This generates a cropped GIF file.

The resources

  • libgif-js
  • gif.js

This project complete code: GitHub repository

Online effect demonstration

Blog Post

conclusion

This project does not make too many complicated Settings, just meet the function of cropping GIF, because I only need to crop GIF to a specified size, so there are not too many customized functions

Personal blog source this project also launched the function source project | blog address

I created a new group to learn from each other, no matter you are preparing for the pit, or halfway into the students, I hope we can share and exchange together. QQ group: 810018802, click join

QQ group The public,
Front end clutter

Wax gourd random