Saber 酱的抱枕

Fly me to the moon

05/2
2017
学习

使用toBlob()方法将canvas对象转换为Blob对象

前情提要:
《在JavaScript中创建Blob对象》
《使用canvas将图片转换为base64编码》

之前的这两篇文章都是为在网页上下载文件而服务的。Blob对象可以通过URL.createObjectURL(blob)方法来生成一个blob协议的url,而canvas可以通过canvas.toDataURL()来生成一个base64编码的url。这两种url都可以用a标签的download属性来下载。

注意:
将数据(包括canvas对象)转换为blob时,会受到跨域限制。
canvas酱图片转换为base64编码时也会受到跨域限制。
使用a标签下载文件时,在firefox里会受到跨域限制。

之前我没发现canvas对象是可以转换成Blob对象的,今天才知道有一个HTMLCanvasElement.toBlob()方法可以做到。

语法如下:

canvas.toBlob(callback, mimeType, qualityArgument);

说人话:

canvas.toBlob(function(blob) {
	// code...
},"image/jpeg", 0.8);

toBlob方法内有一个回调函数,其参数就是canvas对象转换后的生成的blob对象;
如果缺少mimeType参数,则默认为png格式。

相比使用base64编码的url,blob格式的url更加简洁,我喜欢后者。不过base64编码其实储存的是文件本身,它方便重复使用。而blob对象则在刷新页面后就没了,blob格式的url也就不能重用了。

如下代码,先加载一个图片,然后将其绘制在canvas里,之后将canvas元素转化为blob对象,再用一个a标签来做下载功能。

var Img = new Image();
Img.src = "58319482.jpg";
Img.onload = function() {
	var canvas = document.createElement("canvas");
	canvas.width = Img.width;
	canvas.height = Img.height;
	canvas.getContext("2d").drawImage(Img, 0, 0, Img.width, Img.height); //将图片绘制到canvas中
	canvas.toBlob(function(blob) {
		var downloadA = document.createElement("a");
		document.body.appendChild(downloadA);
		downloadA.style.display = "none";
		downloadA.setAttribute("download", "download.jpg");
		downloadA.setAttribute("href", URL.createObjectURL(blob));
		downloadA.click();
	}, "image/jpeg", 0.8);
};

使用toBlob()方法将canvas对象转换为Blob对象

04/8
2017
学习

使用canvas将图片转换为base64编码

如果我们要在网页上处理图片,对于字符形式接收到的图片(比如用ajax获取的图片)可以将其转换为blob对象。但对于img标签(或通过new Image()对象获取的图片)来说,它们不是字符形式,而是html元素,不能转换成blob对象。

要使用这样的图片,我们可以先将图片绘制到canvas里,再使用canvas对象的toDataURL方法获取图片的base64编码(也就是data: URI)。

ps:blob对象和data: URI都可以用a标签的download属性来下载图片~

1.如下代码展示用image对象获取一张图片并转换为base64:

var dataURL="";
var Img = new Image();
Img.crossOrigin = "Anonymous";
Img.src="/f/head15.jpg";
Img.onload=function(){
	var canvas = document.createElement("canvas");
    canvas.width=Img.width;
    canvas.height=Img.height;
    canvas.getContext("2d").drawImage(Img,0,0,Img.width,Img.height); //将图片绘制到canvas中
    dataURL=canvas.toDataURL('image/png'); //转换图片为dataURL
};

注意image对象的crossOrigin 属性:

Img.crossOrigin = "Anonymous";

它在下面的情况中是有用的:
图片跨域了,但有个好消息是图片的服务器允许跨域。这时你加上这个crossOrigin属性就ok了,图片可以正常用。

但如果图片跨域了,并且图片的服务器【不允许】跨域,那你加上也没用,无解。

如果没解决跨域限制,canvas.toDataURL方法将报错,导致程序终止:

Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.

2.如下代码展示从页面上的img标签获取图片内容,并将其转换为base64:

// 记得要在图片加载完成后执行
var image=document.querySelector("img"),
	canvas,
	dataURL;
image.onload=function () {
	canvas = document.createElement("canvas");
	canvas.width = image.width;
	canvas.height = image.height;
	canvas.getContext("2d").drawImage(image, 0, 0);
	dataURL=canvas.toDataURL('image/png'); //转换图片为dataURL
};

3.如果我们是要把图片用于下载的,那么对于色彩复杂、宽高较大的图片,用png格式显然体积会很大,可以转换成jpg的:

dataURL=canvas.toDataURL('image/jpeg',0.5);

经试验完全可用。另外chrome的话还可指定为 image/webp 。

参考资料来自MDN

4.扩展:现在各大浏览器只支持转换成png和jpeg格式,如果需要gif格式或bmp格式怎么办呢?可以用canvas2image.js

canvas2image支持将canvas里的图片数据转换为png、jpeg、gif、bmp格式,并可修改生成的图片的宽高。

你可以仅转换但不下载,也可直接下载。like this:

Canvas2Image.saveAsImage(canvasObj, width, height, type)
Canvas2Image.saveAsPNG(canvasObj, width, height)
Canvas2Image.saveAsJPEG(canvasObj, width, height)
Canvas2Image.saveAsGIF(canvasObj, width, height)
Canvas2Image.saveAsBMP(canvasObj, width, height)

Canvas2Image.convertToImage(canvasObj, width, height, type)
Canvas2Image.convertToPNG(canvasObj, width, height)
Canvas2Image.convertToJPEG(canvasObj, width, height)
Canvas2Image.convertToGIF(canvasObj, width, height)
Canvas2Image.convertToBMP(canvasObj, width, height)

使用canvas将图片转换为base64编码