关于javascript:GIF图片裁剪出指定大小的GIF图片

42次阅读

共计 2134 个字符,预计需要花费 6 分钟才能阅读完成。

前言

最近在博客后盾上传图片的时候,忽然发现上传 gif 图片的时候裁剪图片有问题。既没法裁剪 gif 指定区域的图片,又没法裁剪指定区域生成一个新的指定大小的 gif 图。原本想间接去找个裁剪的库间接放上去的,然而找了半天也没找到可能 裁剪 gif 而后生成裁剪区域的 gif的库, 于是就本人入手了。

摸索

如果只是单纯的在 Gif 上裁剪第一帧图片,倒是有插件能实现,我用的就是 react-cropper 来进行图片裁剪的。然而这个插件没法裁剪 GIF 生成另一个 GIF 图。

我要的成果是上面这样的成果

原图

裁剪后的 gif 图

而后就去查了下如何实现 gif 图到 gif 图的裁剪,尽管没有找到对应的插件,然而找到了两个开源的库。

  1. libgif-js 通过解析 GIF,生成 Canvas
  2. 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 对象,所以须要对这个文件进行局部批改

  1. 首先应该接管的是一个 url 门路, 能够把 File 文件 通过 URL.createObjectURL(file) 转成成 url, 让其进行XMLHttpRequest 申请。也能够间接传 gif 的链接。
  2. 而后须要传裁剪的区域范畴。裁剪的范畴大小须要适配原 gif 的尺寸比例
  3. 去除 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 群 公众号
前端打杂群
冬瓜书屋

正文完
 0