canvas内容保存成文件以及压缩图片相关的api

最近做了两个项目,一个是调用pc端系统摄像头,然后截图上传给服务器,这里有两个api可以用,这两个api在HTMLCanvasElement里。

所谓html canvas元素接口:

DOM canvas元素暴露了HTMLCanvasElement接口,该接口提供了用来操作一个canvas元素布局和呈现的属性和方法.HTMLCanvasElement接口继承了element接口的属性和方法

以致于部分同学没有找到相关api,特此记录一下。

1.HTMLCanvasElement.toBlob()

这个api就是把canvas的内容保存成文件,这样我们就可以把这个文件扔到formData里然后ajax提交给后端接口了formData文档见这里

示例代码如下:

var canvas = document.getElementById("canvas");

canvas.toBlob(function(blob) {
  var formData = new FormData();
  formData.append('img', blob, 'canvas.jpg');
  //然后把这个formData扔给ajax就好了。babababa
});

压缩图片示例代码如下

canvas.toBlob(function(blob){...}, "image/jpeg", 0.95); // JPEG at 95% quality

注意事项:移动端不支持这个api。。。


2.HTMLCanvasElement.toDataURL()

这个api大家比较熟悉,就是把图片变成base64编码的。。然后当成字符串扔给服务端。服务端再解析成img。

示例代码如下:

var canvas = document.getElementById("canvas");
var dataURL = canvas.toDataURL();
console.log(dataURL);
//压缩jpg
var fullQuality = canvas.toDataURL("image/jpeg", 1.0);
// data:image/jpeg;base64,/9j/4AAQSkZJRgABAQ...9oADAMBAAIRAxEAPwD/AD/6AP/Z"
var mediumQuality = canvas.toDataURL("image/jpeg", 0.5);
var lowQuality = canvas.toDataURL("image/jpeg", 0.1);

注意事项:

这个api在iPhone上使用摄像头拍照的源作为canvas内容的时候然后base64之后有照片旋转的bug。

解决办法就是引入exif.js来修正这个bug。

示例代码:

function selectFileImage(fileObj) {
	var file = fileObj.files['0'];
	//图片方向角 added by lzk
	var Orientation = null;
	
	if (file) {
		console.log("正在上传,请稍后...");
		var rFilter = /^(image/jpeg|image/png)$/i; // 检查图片格式
		if (!rFilter.test(file.type)) {
			//showMytips("请选择jpeg、png格式的图片", false);
			return;
		}
		// var URL = URL || webkitURL;
		//获取照片方向角属性,用户旋转控制
		EXIF.getData(file, function() {
		   // alert(EXIF.pretty(this));
		    EXIF.getAllTags(this); 
		    //alert(EXIF.getTag(this, 'Orientation')); 
		    Orientation = EXIF.getTag(this, 'Orientation');
		    //return;
		});
		
		var oReader = new FileReader();
		oReader.onload = function(e) {
			//var blob = URL.createObjectURL(file);
			//_compress(blob, file, basePath);
			var image = new Image();
			image.src = e.target.result;
			image.onload = function() {
				var expectWidth = this.naturalWidth;
				var expectHeight = this.naturalHeight;
				
				if (this.naturalWidth > this.naturalHeight && this.naturalWidth > 800) {
					expectWidth = 800;
					expectHeight = expectWidth * this.naturalHeight / this.naturalWidth;
				} else if (this.naturalHeight > this.naturalWidth && this.naturalHeight > 1200) {
					expectHeight = 1200;
					expectWidth = expectHeight * this.naturalWidth / this.naturalHeight;
				}
				var canvas = document.createElement("canvas");
				var ctx = canvas.getContext("2d");
				canvas.width = expectWidth;
				canvas.height = expectHeight;
				ctx.drawImage(this, 0, 0, expectWidth, expectHeight);
				var base64 = null;
				//修复ios
				if (navigator.userAgent.match(/iphone/i)) {
					console.log('iphone');
					//alert(expectWidth + ',' + expectHeight);
					//如果方向角不为1,都需要进行旋转 added by lzk
					if(Orientation != "" && Orientation != 1){
						alert('旋转处理');
						switch(Orientation){
						 	case 6://需要顺时针(向左)90度旋转
						 		alert('需要顺时针(向左)90度旋转');
						 		rotateImg(this,'left',canvas);
						 		break;
						 	case 8://需要逆时针(向右)90度旋转
						 		alert('需要顺时针(向右)90度旋转');
						 		rotateImg(this,'right',canvas);
						 		break;
						 	case 3://需要180度旋转
						 		alert('需要180度旋转');
								rotateImg(this,'right',canvas);//转两次
								rotateImg(this,'right',canvas);
								break;
						}		
					}
					
					/*var mpImg = new MegaPixImage(image);
					mpImg.render(canvas, {
						maxWidth: 800,
						maxHeight: 1200,
						quality: 0.8,
						orientation: 8
					});*/
					base64 = canvas.toDataURL("image/jpeg", 0.8);
				}else if (navigator.userAgent.match(/Android/i)) {// 修复android
					var encoder = new JPEGEncoder();
					base64 = encoder.encode(ctx.getImageData(0, 0, expectWidth, expectHeight), 80);
				}else{
					//alert(Orientation);
					if(Orientation != "" && Orientation != 1){
						//alert('旋转处理');
						switch(Orientation){
						 	case 6://需要顺时针(向左)90度旋转
						 		alert('需要顺时针(向左)90度旋转');
						 		rotateImg(this,'left',canvas);
						 		break;
						 	case 8://需要逆时针(向右)90度旋转
						 		alert('需要顺时针(向右)90度旋转');
						 		rotateImg(this,'right',canvas);
						 		break;
						 	case 3://需要180度旋转
						 		alert('需要180度旋转');
								rotateImg(this,'right',canvas);//转两次
								rotateImg(this,'right',canvas);
								break;
						}		
					}
					
					base64 = canvas.toDataURL("image/jpeg", 0.8);
				}
				//uploadImage(base64);
				$("#myImage").attr("src", base64);
			};
		};
		oReader.readAsDataURL(file);
	}
}

//对图片旋转处理 added by lzk
function rotateImg(img, direction,canvas) {  
		//alert(img);
        //最小与最大旋转方向,图片旋转4次后回到原方向  
        var min_step = 0;  
        var max_step = 3;  
        //var img = document.getElementById(pid);  
        if (img == null)return;  
        //img的高度和宽度不能在img元素隐藏后获取,否则会出错  
        var height = img.height;  
        var width = img.width;  
        //var step = img.getAttribute('step');  
        var step = 2;  
        if (step == null) {  
            step = min_step;  
        }  
        if (direction == 'right') {  
            step++;  
            //旋转到原位置,即超过最大值  
            step > max_step && (step = min_step);  
        } else {  
            step--;  
            step < min_step && (step = max_step);  
        }  
        //img.setAttribute('step', step);  
        /*var canvas = document.getElementById('pic_' + pid);  
        if (canvas == null) {  
            img.style.display = 'none';  
            canvas = document.createElement('canvas');  
            canvas.setAttribute('id', 'pic_' + pid);  
            img.parentNode.appendChild(canvas);  
        }  */
        //旋转角度以弧度值为参数  
        var degree = step * 90 * Math.PI / 180;  
        var ctx = canvas.getContext('2d');  
        switch (step) {  
            case 0:  
                canvas.width = width;  
                canvas.height = height;  
                ctx.drawImage(img, 0, 0);  
                break;  
            case 1:  
                canvas.width = height;  
                canvas.height = width;  
                ctx.rotate(degree);  
                ctx.drawImage(img, 0, -height);  
                break;  
            case 2:  
                canvas.width = width;  
                canvas.height = height;  
                ctx.rotate(degree);  
                ctx.drawImage(img, -width, -height);  
                break;  
            case 3:  
                canvas.width = height;  
                canvas.height = width;  
                ctx.rotate(degree);  
                ctx.drawImage(img, -width, 0);  
                break;  
        }  
    }

相关文档见这里


1.利用exif.js解决ios手机上传竖拍照片旋转90度问题

2.exif.js文档

本文标题:canvas内容保存成文件以及压缩图片相关的api
本文链接:https://56way.com/p/94.html
作者授权:除特别说明外,本文由 无路 原创编译并授权 小无路 刊载发布。
版权声明:本文不使用任何协议授权,您可以任何形式自由转载或使用。

发表评论

必填

选填

选填

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。