项目需求(对app的轮播,以及banner和咨询的图片进行裁剪):前期实现使用用vue-cropper插件对图片进行插件,----后续需求需要裁剪gif动图(vue-cropper、微信自带的截图工具,以及fastStone截图工具,都只能截取静态图片,打开动图时只显示某一帧的静态图片),所以需要研究为什么vue-cropper明明打开的是gif图,而结果显示的确实某一帧???对于上传图片的操作使用type=file的html标签,选中某个文件后产生文件流,然后我们将文件流转化为base64,通过img的src引入时,动图可以显示,但是通过vue-cropper这个插件中的组件src属性引入时,页面只能显示某一帧图片,所以vue-cropper插件不支持裁剪动图,
实现思路:仿照vue-cropper(没有现成的裁剪gif组件)
实现思路:三步很简单,但实现起来不容易(涉及到三个js库)
(1)上传gif动图,通过img标签显示在页面上
(2)在图片上显示裁剪框
(3)解析gif动图的某一帧,然后将每一帧生成canvas图像(每一帧都是一个图片,生成的图像已经是被裁剪过了的);
(4)将canvas图像转化为gif,通过addFrame收集canvas图像,收集完毕后调用render合成;
三个js库的作用—涉及到三个构造函数Cropper、GifToCanvas、Gif
(1)cropperjs显示裁剪框的组件,有一个Cropper 构造函数
(2)libgif-js库:通过实现对gif路径(通过第一步生成)发起一个请求,然后通过解析请求回来的gif数据来生成GIF实例(包括每一帧的动画,以及大小之类的基础数据),然后通过GIF实例生成对应的canvas,有一个GifToCanvas
(3)gif.js库:通过收集libgif库转换到canvas上面的每一帧的变化,来生成最终的GIF
具体实现:
(1)点击type=file的input标签选择文件,选中文件后拿到的是文件流,将文件流转化为base64,通过img标签显示到页面上;
(2)需要使用cropperjs库生成页面上的裁剪框,new Cropper构造函数(两个入参:当前image标签和裁剪框的大小等配置),构造函数的实例中包含了一些属性和方法(或者当前图片的url拿到的是base64,getCropData或者裁剪框的数据)
(3)需要将gif转化为canvas,libgif-js库,这个库中有一个GifToCanvas的构造函数,需要两个参数(第一个是gif图片的url—是可供浏览器使用的url,所以需将第一步拿到的base64—>blob—>window.URL.createObjectURL),第二个参数裁剪的尺寸区域;—
核心有一个onProgress这个方法;在这个方法中我们可以收集到动图的每一帧转化的canvas图像,所以我们需要在这个方法中将处理好的每一帧对应的canvas图像进行收集,是通过gifjs库中的一个addFrame方法来收集的;
(4)将canvas生成gif动图—通过Gifjs库来实现,有一个Gif 构造函数,构造函数中创建出来的实例对象上有一个方法addFrame,在gif转化为canvas过程中即onProgress方法中,调用addFrame进行canvas收集(对每一帧图片进行裁剪生成canvas),收集完所有的canvas图像后,调用.render方法进行gif动图合成;
参考