利用canvas中toDataURL()将图片转为dataURL(base64)的方法详解


Posted in Javascript onNovember 20, 2017

将图片转为base64的好处

将图片转换为Base64编码,可以让你很方便地在没有上传文件的条件下将图片插入其它的网页、编辑器中。 这对于一些小的图片是极为方便的,因为你不需要再去寻找一个保存图片的地方。

将图片转换成base64编码的,在web网上一般用于小图片上,不仅可以减少图片的请求数量(集合到js、css代码中),还可以防止因为一些相对路径等问题导致图片404错误。

引言

假设一个应用场景:由于某些特殊原因从服务端请求到图片路径,要求通过该路径获取对应图片的 base64 dataURL。在这个场景中,我们首先推断该图片路径是可访问的,同时还需要一种将图片转换到 dataURL 的方法。

我们如何实现它呢?

dataURL

先大致回顾下正统的 dataURL 的语法,这有助于我们检验转换后的内容是否正确。一个完整的 dataURI 应该是这样的:

data:[<mediatype>][;base64],<data>

其中mediatype声明了文件类型,遵循MIME规则,如“image/png”、“text/plain”;之后是编码类型,这里我们只涉及 base64;紧接着就是文件编码后的内容了。我们常常在 HTML 里看到img标签的src会这样写:

src="data:image/gif;base64,R0lGODdhMAAwAPAAAAAAAP///ywAAAAAMAAwAAAC8IyPqcvt3wCcDkiLc7C0qwyGHhSWpjQu5yqmCYsapyuvUUlvONmOZtfzgFzByTB10QgxOR0TqBQejhRNzOfkVJ+5YiUqrXF5Y5lKh/DeuNcP5yLWGsEbtLiOSpa/TPg7JpJHxyendzWTBfX0cxOnKPjgBzi4diinWGdkF8kjdfnycQZXZeYGejmJlZeGl9i2icVqaNVailT6F5iJ90m6mvuTS4OK05M0vDk0Q4XUtwvKOzrcd3iq9uisF81M1OIcR7lEewwcLp7tuNNkM3uNna3F2JQFo97Vriy/Xl4/f1cf5VWzXyym7PHhhx4dbgYKAAA7"

这个img引用的就是以 base64 编码的 dataURL 了,只要浏览器支持,就可以被解码成 gif 图片并渲染出来。

.toDataURL()

FileReader对象也有类似的方法,比如.readAsDataURL() ,然而它只接受file或blob类型,而这两种类型一般只能通过<input[type=file]>元素的files属性获取,或者用Blob()构造函数手工创建一个新的对象。尴尬的是我们当前只有图片路径,受制于浏览器的安全策略, <input[type=file]>的files属性是只读的,而Blob()构造函数只接受文件内容,两种方式都无法通过图片路径直接获取。上文中假设的应用场景迫使我们必先考虑如何通过路径获取到图片内容。<img>是可以的,并且可以被绘制到<canvas>中,而<canvas>正巧拥有.toDataURL()方法。

万事具备,我们只需要把<img>获取到的图片放到<canvas>里再通过.toDataURL()方法转化下,就可以得到以 base64 编码的 dataURL。来看这个方法的语法:

canvas.toDataURL([type, encoderOptions]);

canvas是DOM元素<canvas>对象;参数type指定图片类型,如果指定的类型不被支持则以默认值image/png替代;encoderOptions可以为image/jpeg或image/webp类型的图片设置图片质量,取值0-1,超出则以默认值0.92替代。

需要注意的是:在转换成 dataURL 前必须先确保图片成功加载到,于是.toDataURL()方法应该写在<img>的onload异步事件中。现在就来实现一个功能函数:

function getBase64(url){
  //通过构造函数来创建的 img 实例,在赋予 src 值后就会立刻下载图片,相比 createElement() 创建 <img> 省去了 append(),也就避免了文档冗余和污染
  var Img = new Image(),
   dataURL='';
  Img.src=url;
  Img.onload=function(){ //要先确保图片完整获取到,这是个异步事件
   var canvas = document.createElement("canvas"), //创建canvas元素
    width=Img.width, //确保canvas的尺寸和图片一样
    height=Img.height;
   canvas.width=width;
   canvas.height=height;
   canvas.getContext("2d").drawImage(Img,0,0,width,height); //将图片绘制到canvas中
   dataURL=canvas.toDataURL('image/jpeg'); //转换图片为dataURL
  };
 }

一个可供随时调用的转换函数完成了,它会在图片被加载后返回一整个 dataURL 字符串。

完善

onload事件确保了转换任务在加载后执行,却又带来了新问题——dataURL 只有在图片加载完成后才会返回,我们无法确定图片什么时候完成加载。如果后续要对 dataURL 做相关处理(比如传递到其他服务器)的话,添加一个回调是必要的,这能确保后续处理任务在成功得到 dataURL 之后执行,我们需要修改getBase64()

function getBase64(url,callback){ //添加一个回调参数
  ...
  Img.onload=function(){
   ...
   canvas.getContext("2d").drawImage(Img,0,0,width,height);
   dataURL=canvas.toDataURL('image/jpeg');
   callback?callback(dataURL):null; //调用回调函数
  };
 }

在执行时添加回调:

getBase64('//upload.jianshu.io/users/upload_avatars/555630/fdd1b798e6b0.jpg',(dataURL)=>{
  console.log(dataURL);
 });

就是这样,如果不考虑兼容性的话,或许我们可以用 promise 和 generator 来实现,再添加一些错误处理就更完美了。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
一次失败的jQuery优化尝试小结
Feb 06 Javascript
推荐20家国外的脚本下载网站
Apr 28 Javascript
深入理解javascript构造函数和原型对象
Sep 23 Javascript
使用jquery 简单实现下拉菜单
Jan 14 Javascript
JS实现弹出浮动窗口(支持鼠标拖动和关闭)实例详解
Aug 06 Javascript
JS获取地址栏参数的两种方法(简单实用)
Jun 14 Javascript
浅谈angular懒加载的一些坑
Aug 20 Javascript
详解JS几种变量交换方式以及性能分析对比
Nov 25 Javascript
微信小程序版翻牌小游戏
Jan 26 Javascript
Vue.js 使用v-cloak后仍显示变量的解决方法
Nov 19 Javascript
解决LayUI加上form.render()下拉框和单选以及复选框不出来的问题
Sep 27 Javascript
webpack3.0升级4.0的方法步骤
Apr 02 Javascript
Node.js 中使用 async 函数的方法
Nov 20 #Javascript
利用three.js画一个3D立体的正方体示例代码
Nov 19 #Javascript
IE11下使用canvas.toDataURL报SecurityError错误的解决方法
Nov 19 #Javascript
使用DataTable插件实现异步加载数据
Nov 19 #Javascript
原生JavaScript实现Ajax异步请求
Nov 19 #Javascript
gulp安装以及打包合并的方法教程
Nov 19 #Javascript
js实现rem自动匹配计算font-size的示例
Nov 18 #Javascript
You might like
详解PHP编码转换函数应用技巧
2016/10/22 PHP
PHP十六进制颜色随机生成器功能示例
2017/07/24 PHP
Firefox outerHTML实现代码
2009/06/04 Javascript
替代window.event.srcElement效果的可兼容性的函数
2009/12/18 Javascript
jquery对表单操作2
2011/04/06 Javascript
关于图片按比例自适应缩放的js代码
2011/10/30 Javascript
模拟电子签章盖章效果的jQuery插件源码
2013/06/24 Javascript
jQuery 获取和设置select下拉框的值实现代码
2013/11/08 Javascript
jquery实现pager控件示例
2014/04/09 Javascript
javascript 10进制和62进制的相互转换
2014/07/31 Javascript
jquery分析文本里url或邮件地址为真实链接的方法
2015/06/20 Javascript
如何用jQuery实现ASP.NET GridView折叠伸展效果
2015/09/26 Javascript
一些实用性较高的js方法
2016/04/19 Javascript
微信公众平台开发教程(五)详解自定义菜单
2016/12/02 Javascript
Javascript 制作图形验证码实例详解
2016/12/22 Javascript
Agularjs妙用双向数据绑定实现手风琴效果
2017/05/26 Javascript
微信小程序通过保存图片分享到朋友圈功能
2018/05/24 Javascript
详解Vue的常用指令v-if, v-for, v-show,v-else, v-bind, v-on
2018/10/12 Javascript
[01:09]模型精美,特效酷炫!TI9不朽宝藏Ⅰ鉴赏
2019/05/10 DOTA
Python循环语句中else的用法总结
2016/09/11 Python
浅谈Python类里的__init__方法函数,Python类的构造函数
2016/12/10 Python
解决Python安装时报缺少DLL问题【两种解决方法】
2019/07/15 Python
Pyorch之numpy与torch之间相互转换方式
2019/12/31 Python
python如何实现单链表的反转
2020/02/10 Python
如何对python的字典进行排序
2020/06/19 Python
详解pycharm配置python解释器的问题
2020/10/15 Python
关于html字符串正则判断和匹配的具体使用
2019/12/12 HTML / CSS
德国高端单身人士交友网站:ElitePartner
2018/12/02 全球购物
be2台湾单身男女交友:全球网路婚姻介绍的领导品牌
2019/10/11 全球购物
Engel & Bengel官网:婴儿推车、儿童房家具和婴儿设备
2019/12/28 全球购物
幼儿园课题方案
2014/06/09 职场文书
上班迟到检讨书
2014/09/15 职场文书
办公用房租赁协议书
2014/11/29 职场文书
会计出纳岗位职责
2015/03/31 职场文书
CSS精灵图的原理与使用方法介绍
2022/03/17 HTML / CSS
python实现双链表
2022/05/25 Python