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

将图片转为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 来实现,再添加一些错误处理就更完美了。

总结

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

(0)

相关推荐

  • 使用原生js+canvas实现模拟心电图的实例

    从2015年2月转行进入IT行业,到现在也有将近两年的时间了,从最开始的java到现在的前端,前进的路上一直靠自己摸索,一路走到现在,前端大神是绝对谈不上的,最多算一只刚入门的菜鸟. 从最开始的懵懵懂懂,到现在学着开始写github.写博客,其实技术上没有太多可写的,毕竟自己也才刚刚入门,只能说是按照自己的兴趣,写点有意思的小项目,项目上存在的问题,也希望大神能够予以指正,目前这个demo的功能已经实现,后期我会对样式.代码等方面进行优化. 项目运行效果: 项目简介:使用原生js+canvas制

  • Js利用Canvas实现图片压缩功能

    最近做的APP项目涉及到手机拍照上传图片,因为手机拍照的图片通常都比较大,所以上传的时候就会很慢.为此,需要对图片进行压缩处理来优化上传功能.以下是具体实现: /* * 图片压缩 * img 原始图片 * width 压缩后的宽度 * height 压缩后的高度 * ratio 压缩比率 */ function compress(img, width, height, ratio) { var canvas, ctx, img64; canvas = document.createElement

  • canvas基础绘制-绚丽倒计时的实例

    效果图: html: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>ball</title> <script src="digit_1.js"></script> <script src="countdown.js"></

  • JS+canvas画一个圆锥实例代码

    以下是我们给大家分享是实例代码: <html> <head> <title>我的第一个 HTML 页面</title> </head> <body> <canvas id='cvs' width='1000' height="800"> </canvas> <script> const cvs =document.getElementById('cvs'); // 计算画布的宽度

  • JavaScript canvas实现围绕旋转动画

    使用canvas的convas来实现围绕旋转动画,外圈顺时针,里层逆时针 代码demo链接地址:代码demo链接地址 html文件 <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> <style> body { margin: 0; padding: 0; overflow:

  • 一步步教你利用Canvas对图片进行处理

    前言 Canvas,中文译为"画布",HTML5中新增了<canvas>元素,可以结合JavaScript动态地在画布中绘制图形. 今天,我们不讲Canvas的图形绘制,而是讲如何对图片进行处理,话不多说了,来一起看看详细的介绍吧. 大概流程非常简单,主要分为以下三个步骤: Canvas图片处理 是的,就像把大象装进冰箱一样简单,哈哈. 一.主要API 整个流程中所用到的主要Canvas API有: 绘制图像: drawImage() 获取图像数据: getImageDat

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

    将图片转为base64的好处 将图片转换为Base64编码,可以让你很方便地在没有上传文件的条件下将图片插入其它的网页.编辑器中. 这对于一些小的图片是极为方便的,因为你不需要再去寻找一个保存图片的地方. 将图片转换成base64编码的,在web网上一般用于小图片上,不仅可以减少图片的请求数量(集合到js.css代码中),还可以防止因为一些相对路径等问题导致图片404错误. 引言 假设一个应用场景:由于某些特殊原因从服务端请求到图片路径,要求通过该路径获取对应图片的 base64 dataURL

  • JS中call/apply、arguments、undefined/null方法详解

    a.call和apply方法详解 -------------------------------------------------------------------------------- call方法: 语法:call([thisObj[,arg1[, arg2[, [,.argN]]]]]) 定义:调用一个对象的一个方法,以另一个对象替换当前对象. 说明: call 方法可以用来代替另一个对象调用一个方法.call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指

  • Java实现字符串转为驼峰格式的方法详解

    字符串转为驼峰格式 构建工具类 package com.yt.common.util; import com.yt.common.dto.NameCode; import com.yt.exam.enums.ZyEnum; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * 字符串转为驼峰格式 构建工具类 * @author LYY * @date 2022/07

  • Python实现普通图片转ico图标的方法详解

    目录 简介 历史攻略 下载安装包 下载地址 安装后缀pythonmagick - whl文件 案例源码 效果图 简介 ICO是一种图标文件格式,图标文件可以存储单个图案.多尺寸.多色板的图标文件.一个图标实际上是多张不同格式的图片的集合体,并且还包含了一定的透明区域.它是图标文件格式的一种,可以存储单个图案.多尺寸.多色板的图标文件.图标是具有明确指代含义的计算机图形.其中桌面图标是软件标识,界面中的图标是功能标识. 历史攻略 pip安装第三方库全攻略:普通安装.安装whl后缀文件.使用国内镜像

  • 关于java中可变长参数的定义及使用方法详解

    JAVA中可以为方法定义可变长参数( Varargs)来匹配不确定数量的多个参数,其定义用"..."表示.其实,这类似于为方法传了一个数组,且在使用方法上也和数组相同,如下: public void test(String... str){ for(String s : str){ } } 调用方法就像普通的调用方式相同,只不过可以匹配的参数为0到多个.如下: test(); test("lilei"); test("lilei","h

  • 对python中xlsx,csv以及json文件的相互转化方法详解

    最近需要各种转格式,这里对相关代码作一个记录,方便日后查询. xlsx文件转csv文件 import xlrd import csv def xlsx_to_csv(): workbook = xlrd.open_workbook('1.xlsx') table = workbook.sheet_by_index(0) with codecs.open('1.csv', 'w', encoding='utf-8') as f: write = csv.writer(f) for row_num

  • 对Python中一维向量和一维向量转置相乘的方法详解

    在Python中有时会碰到需要一个一维列向量(n*1)与另一个一维列向量(n*1)的转置(1*n)相乘,得到一个n*n的矩阵的情况.但是在python中, 我们发现,无论是".T"还是"np.transpose"都无法实现一维向量的转置,相比之下,Matlab一句" a' "就能实现了. 那怎么实现呢?我找了个方法.请看: 即,我们把向量reshape一下,如此便实现了一维向量与一维向量转置相乘为矩阵的目的. 若大家有其他方法望告知. 以上这篇对

  • 在Pycharm中对代码进行注释和缩进的方法详解

    一.注释 1. #单行注释 2. """ 多行注释 """ 3. pycharm多行注释快捷键:Ctrl+/ 二.缩进 缩进:Tab 反向缩进:Shift+Tab 以上这篇在Pycharm中对代码进行注释和缩进的方法详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们.

  • 对numpy中二进制格式的数据存储与读取方法详解

    使用save可以实现对numpy数据的磁盘存储,存储的方式是二进制.查看使用说明,说明专门提到了是未经压缩的二进制形式.存储后的数据可以进行加载或者读取,通过使用load方法. In [81]:np.save('demo',data1) 通过以上操作,数据data1被存储到了demo文件中,numpy会自动加上npy的文件后缀名. In [82]: a =np.load('demo.npy') In [83]: a Out[83]: array([0,1, 2, 3, 4, 5, 6, 7, 8

  • c++中的单例类模板的实现方法详解

     1.什么是单例模式 在架构设计时,某些类在整个系统生命周期中最多只能有一个对象存在 ( Single Instance ).如超市收银系统,其外观主要由显示器(1个).扫描枪(1个).收款箱(1个)组成,在系统正常运行期间这三部分都是唯一存在的:也就是说,显示器.扫描枪.收款箱这三部分都应该有各自的类,并且每个类只能唯一地实例化一个对象,基于这种模式的程序设计,称为单例模式. !!!单例模式只能创建一个对象,且该对象的生命周期伴随系统的整个运行期间. 2.怎么实现单例模式 思考:如何定义一个类

随机推荐