js将用户上传gif动图分解成多张帧图片
js将用户上传gif动图分解成多张帧图片
写在前面
工作中遇到一个这么一个需求:这是一个多图上传的场景,如果用户上传选择多张图片,则上传后直接展示多张图片,如果上传的图片是gif动图,则需要分解这张动图拆分成一帧一帧的单张图片,再按顺序展示出来。
实现思路
这里主要针对gif分解多图的实现
- 首先对用户上传的文件格式进行判断;
- 将gif动图经过gif库解析成gif实例
- 遍历获取gif实例的每一帧的canvas,转换成baseURL,再转一份file对象存放起来。
- 通过转换后的baseURL展示到界面,用户点上传就把对应的file对象上传服务器。
这里最核心的就是2,3步,非常庆幸有https://github.com/buzzfeed/libgif-js 这个库,才得以实现后面的步骤;
代码部分
由于是公司项目就不展示界面和完整代码,只放关键代码:
0. 引入gif库
import { SuperGif } from './libgif.js'
1. 对用户上传的文件格式进行判断
// 判断文件格式并展示的函数
pre_upload() {
// 点击上传按钮触发弹出文件选择框
const input = document.createElement('input');
input.setAttribute('type', 'file');
// 注意要设置多选属性
input.setAttribute('multiple', 'true');
input.addEventListener('change', (e) => {
this.img_list = [];
this.can_upload = true;
this.qiniu_url_list = [];
// 判断是gif格式则交给this.pre_load_gif函数处理
if (/(image\/gif)/.test(e.path[0].files[0].type)) {
this.pre_load_gif(e.path[0].files[0])
return;
}
// 如果是上传多张静态的png、jpg图片则直接转换成baseURL
var img_list = [];
for(let i=0,item; item = e.path[0].files[i]; i++) {
if (!/(image\/png)|(image\/jp(e?)g)/.test(item.type)) {
alert('请上传jpg、png格式的图片')
return;
}
img_list.push({
file_name: item.name,
url: URL.createObjectURL(item),
file: item,
})
}
this.img_list = img_list
});
input.click();
},
2. 分解gif图片
dataURLtoFile(dataurl, filename) {
const arr = dataurl.split(',');
const mime = arr[0].match(/:(.*?);/)[1];
const bstr = atob(arr[1]);
var n = bstr.length;
const u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename, {type:mime});
},
// 将canvas转换成file对象
convertCanvasToImage(canvas, filename) {
return this.dataURLtoFile(canvas.toDataURL('image/png'), filename);
},
pre_load_gif(gif_source) {
var img_list = [];
const gifImg = document.createElement('img');
// gif库需要img标签配置下面两个属性
gifImg.setAttribute('rel:animated_src', URL.createObjectURL(gif_source))
gifImg.setAttribute('rel:auto_play', '0')
// 新建gif实例
var rub = new SuperGif({ gif: gifImg } );
rub.load(() => {
var img_list = [];
for (let i=1; i <= rub.get_length(); i++) {
// 遍历gif实例的每一帧
rub.move_to(i);
// 将每一帧的canvas转换成file对象
let cur_file = this.convertCanvasToImage(rub.get_canvas(), gif_source.name.replace('.gif', '') + `-${i}`)
img_list.push({
file_name: cur_file.name,
url: URL.createObjectURL(cur_file),
file: cur_file,
})
}
this.img_list = img_list
});
},
至此,核心功能基本实现,上面的函数已经将gif分解成多张图片存放在this.img_list 这个数组里面。
接下来只要拿img_list数组里的file对象上传到服务器即可。
上传方式各不相同,这里就不放具体代码了,需要注意的是,图片上传是异步操作,多图上传需要得知所有的图片全部上传成功才能确定上传完成,所以如果上传的函数返回的是promise对象,则可以直接用Promise.all函数即可得知所有图片上传完毕的回调。
js将用户上传gif动图分解成多张帧图片的更多相关文章
- 用户上传gif动图分解成多张帧图片,并合并生成新gif图片
背景 为什么要制作这么一款工具 首先公司最近在做一款表情包的产品,需要将文字生成到gif图片中,并可以控制文字显示的位置,并将不同的文字显示在不同的图片上 制作成网页端工具,随时随地,方便使用 探索 ...
- Django项目实战之用户上传与访问
1 将文件保存到服务器本地 upload.html <!DOCTYPE html> <html lang="en"> <head> <me ...
- js实现分段上传文件
使用js实现分段上传文件,本文使用了FileReader对象,可参考:https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader 1)获取文 ...
- ubuntu server vsftpd 匿名用户上传下载及目录设置
ubuntu server vsftpd 匿名用户上传下载及目录设置 1:vsftpd服务器安装: sudo apt-get install vsftpd #安装 cd /srv/ #切换到默认匿名用 ...
- springboot配置虚拟路径访问用户上传的附件及图片资源
在springmvc项目中,我们通常把图片及附件存放到WEB-INF/upload类似的路径. springboot项目是通过jar包方式运行的. 笔者曾尝试以下代码,把图片转成base64格式的图片 ...
- JS大文件上传断点续传解决方案
1 背景 用户本地有一份txt或者csv文件,无论是从业务数据库导出.还是其他途径获取,当需要使用蚂蚁的大数据分析工具进行数据加工.挖掘和共创应用的时候,首先要将本地文件上传至ODPS,普通的小文件通 ...
- js文件夹上传
文件夹上传:从前端到后端 文件上传是 Web 开发肯定会碰到的问题,而文件夹上传则更加难缠.网上关于文件夹上传的资料多集中在前端,缺少对于后端的关注,然后讲某个后端框架文件上传的文章又不会涉及文件夹. ...
- JS大文件上传解决方案
1 背景 用户本地有一份txt或者csv文件,无论是从业务数据库导出.还是其他途径获取,当需要使用蚂蚁的大数据分析工具进行数据加工.挖掘和共创应用的时候,首先要将本地文件上传至ODPS,普通的小文件通 ...
- vue : 检测用户上传的图片的宽高
需求: 用户可上传3-6张图片(第 1 2 3 张必须传),上传的图片必须是540 * 330 像素. 第一步,获取上传的图片的宽高. 初始化一个对象数组,宽高均设为0. 如果用户上传的图片没有上限, ...
随机推荐
- luogu P1107 最大整数
题目描述 设有n个正整数 (n<=20), 将它们连接成一排, 组成一个最大的多位整数. 例如: n=3时, 3个整数13, 312, 343连接成的最大整数为: 34331213 又如: n= ...
- BSGS与二次剩余
BSGS $Big\ Step\ Giant\ Step$,大步小步法,一种在$O(\sqrt{p})$内求解方程$a^x\equiv b (mod\ p)$的算法. 先考虑$p$为质数的情况. 令$ ...
- 某考试 T1 lcm
把lcm写成 (a+n)*(b+n) / gcd(a+n,b+n). 因为gcd可以辗转相减,所以就成了gcd(abs(a-b),a+n),一个常量一个变量之间的gcd,我们可以直接把abs(a-b) ...
- POJ 2559 Largest Rectangle in a Histogram(单调栈)
[题目链接] http://poj.org/problem?id=2559 [题目大意] 给出一些宽度为1的长方形下段对其后横向排列得到的图形,现在给你他们的高度, 求里面包含的最大长方形的面积 [题 ...
- Scala零基础教学【102-111】Akka 实战-深入解析
第102讲:通过案例解析Akka中的Actor运行机制以及Actor的生命周期 Actor是构建akka程序的核心基石,akka中actor提供了构建可伸缩的,容错的,分布式的应用程序的基本抽象, a ...
- gzip压缩目录
很遗憾,gzip不能针对整个目录进行压缩,只能递归压缩目录下的每一个文件. 当然,替代方案是只用tar进行打包,比如 tar cfz dir.tar.gz dirname
- 敏捷开发中的sprint是什么意思_百度知道
敏捷开发中的sprint是什么意思_百度知道 敏捷开发中的sprint是什么意思 未成年RB21 | 浏览 4208 次 推荐于2016-02-27 15:19:02 最佳 ...
- sqlserver 调试WINDBG ---troubleshootingsql.com
https://troubleshootingsql.com/tag/stack-dump/ Debugging that latch timeout Posted on August 26, 201 ...
- 解决IIS服务和用户上传的文件分别部署在不同的电脑上时,解决权限的问题
为解决IIS服务和用户上传的文件分别部署在不同的电脑上时,解决权限的问题. 定义: A:iis服务器 B:文件服务器 步骤: 1.在B上创建一个用户[uploaduser](并设置密码) 2.给B上的 ...
- ASP.NET Core 1.0基础之日志
过年出去玩了一圈,回来继续翻译.前两天偷懒没有翻译,只是转了两篇C# 7计划中的新features,大家还是很支持的.现在继续完善这个系列. 来源https://docs.asp.net/en/lat ...