前言

最近在博客后台上传图片的时候,突然发现上传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文件。

参考资源

本项目完整的代码:GitHub 仓库

线上效果演示

博客原文地址

总结

这个项目也没有做太多复杂的设置,满足裁剪GIF的功能就行,因为我目前只需要把gif裁剪成指定大小的gif就行,所以并没有做太多特制化的功能

个人博客源码这个项目也上线了这个功能 | 博客源码项目地址

我自己新创建了一个相互学习的群,无论你是准备入坑的小白,还是半路入行的同学,希望我们能一起分享与交流。

QQ群:810018802, 点击加入

QQ群 公众号
前端打杂群
冬瓜书屋

GIF图片裁剪出指定大小的GIF图片的更多相关文章

  1. PHP JS HTML ASP页面跳转代码 延时跳转代码 返回到上一界面并刷新 JS弹出指定大小的新窗口

    1.PHP延时跳转代码 //跳转到浏览界面 header("Refresh:1;url=machine_list.php"); //不延时 <?php header(&quo ...

  2. iOS学习——图片压缩到指定大小以内

    一.图片压缩简述 在我们开发过程中,有可能会遇到拍照.或者从相册中选择图片,要么单选或者多选,然后上传图片到服务器,一般情况下一张图片可能3-4M,如果类似微信朋友圈上传9张图片大约是 35M左右,如 ...

  3. JS通过指定大小来压缩图片

    安装: npm i image-conversion --save 引入: <script src="https://cdn.jsdelivr.net/gh/WangYuLue/ima ...

  4. Delphi将图片缩放成指定大小

    unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...

  5. 图片转换到指定大小PDF

    1.首先转换为eps jpeg2ps compile to exec file ./jpeg2ps  -p a4  a.jpg -o x.eps2.从eps转换到pdf ps2pdf -dDownsa ...

  6. JQuery获取图片大小并控制图片文件上传大小以及上图片文件时如何预览图片

    首先我们来看效果图: 点击上传之后如下: 在这里我获取到文件的大小,并且如果超出我设定的大小,则禁止上传! 不多说,上代码:先看div布局: <div class="imageCont ...

  7. Python3.7 练习题(三) 将指定目录下的图片进行批量尺寸大小处理

    # 将指定目录下的图片进行批量尺寸大小处理 #修改图片尺寸 导入Image os 快捷键 alt+enter import os from PIL import Image def process_i ...

  8. PHP图片裁剪_图片缩放_PHP生成缩略图

    在制作网页过程中,为了排版整齐美观,对网页中的图片处理成固定大小尺寸的图片,或是要截去图片边角中含有水印的图片,对于图片量多,每天更新大量图,靠人工PS处理是不现实的,那么有没有自动处理图片的程序了! ...

  9. cropper.js图片裁剪

    最近做电子名片的项目,可是个人照片展示上出现了 用户上传的图片尺寸严重失调,所以要求进行图片裁剪,再此我对图片裁剪进行调研 还不太成熟 以后再改 这个实现的原理是 前台获取到 坐标 图片的尺寸 原图文 ...

随机推荐

  1. mongodb导入,导出实例

    MongoDB中文手册|官方文档中文版 英文版:https://docs.mongodb.com/manual/ 1.mongoexport 导出文件 打开命令行,进入我们所安装的mongodb路径下 ...

  2. 【Azure 应用服务】Azure App Service 自带 FTP服务

    问题描述 Azure PaaS服务是否有FTP/S服务呢? 回答问题 应用服务(Web App/App Service)在创建时候,默认创建了FTP服务并自动开启,用于应用部署.但它不是适合作为FTP ...

  3. python基础学习之函数基础和部分内置函数

    在函数调用的时候,必备参数必须要传入 函数定义: def  函数名: 代码块pass return  返回值 函数名命名规则: 字母.数字和下划线组成,和变量命名规则一致 pass在这里表示什么都没有 ...

  4. Go语言学习笔记——Go语言的make的理解

    实例:https://tour.go-zh.org/moretypes/10 谢大<Go Web编程>书中的讲解https://github.com/astaxie/build-web-a ...

  5. OpenGL光照计算中法线矩阵原理及推到过程

    问题起源 在计算漫反射关照时,需要用到法线,通过法线和光线的点乘值,计算漫反射的产生的光线强度,所以需要从顶点着色器中将法线数据传递到片源着色器中,但是片源着色器中的顶点坐标是经过了模型矩阵变化过的世 ...

  6. 走进docker-swarm 带大家快速掌握docker自带编排工具

    什么是Docker Swarm? 对比Docker 前面我们介绍过Docker可以理解成是一个我们的服务的独立运行的容器,那么在实际工作中,我们的系统可能是一个微服务应用,系统中根据业务拆分成多个模块 ...

  7. JS实现鼠标点击爱心&绘制多边形&每日一言功能

    本篇文章主要介绍我的个人博客 程序猿刘川枫 中页面使用的美化功能(基于JS实现): 1.鼠标点击出现不同颜色爱心特效 2.页面浮动多边形跟随鼠标移动 3.每日一言功能 1.鼠标点击出现爱心特效 经常在 ...

  8. HTML5-本地存储浅谈

    Web Storage是HTML5里面引入的一个类似于cookie的本地存储功能,可以用于客户端的本地存储 sessionStorage && localStorage session ...

  9. [Fundamental of Power Electronics]-PART I-2.稳态变换器原理分析-2.3 Boost 变换器实例

    2.3 Boost 变换器实例 图2.13(a)所示的Boost变换器器是另一个众所周知的开关模式变换器,其能够产生幅值大于直流输入电压的直流输出电压.图2.13(b)给出了使用MOSFET和二极管的 ...

  10. Java 获取Word中的标题大纲(目录)

    概述 Word中的标题可通过"样式"中的选项来快速设置(如图1), 图1 在添加目录时,可将"有效样式"设置为"目录级别"显示(如图2),一 ...