随着手机的拍照效果的不断提升,必然使得单张图片的存储变大,几M到十几M不等,因此大图片上传不仅占用服务器资源、耗流量,也影响了用户体验,因而在前端方面有必要用js进行图片压缩。
一、 HTML5 canvas drawImage() 方法
canvas的drawImage()
方法是前端图片压缩的核心方法,其有三种用法:
1 2 3
| var canvas = document.createElement('canvas'); var context = canvas.getContext('2d');
|
** 1.在画布上定位图像 **
context.drawImage(img,x,y);
参数:img
规定要使用的图像、画布或视频;x
在画布放置图像的x坐标位置;y
在画布放置图像的y坐标位置。
** 2.在画布上定位图像,并规定图像的宽度和高度 **
context.drawImage(img,x,y,width,height);
参数:width
可选。要使用的图像的宽度。(伸展或缩小图像);height
可选。要使用的图像的高度。(伸展或缩小图像)。
** 3.剪切图像,并在画布上定位被剪切的部分 **
context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);
参数:sx
可选。开始剪切的x坐标位置;sy
可选。开始剪切的y坐标位置;swidth
可选。被剪切图像的宽度;sheight
可选。被剪切图像的高度。
二、 HTML5 file API 显示图片
HTML5的file API可以在图片上传之前直接在浏览器中显示,通常使用FileReader()
方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| var eleFile = document.querySelector("#imgfile");
var file = null;
var reader = new FileReader(), img = new Image();
reader.onload = function (e) { img.src = e.target.result; }; eleFile.addEventListener('change', function (event) { file = event.target.files[0]; if (file.type.indexOf("image") == 0) { reader.readAsDataURL(file); } });
|
三、 如何把canvas画布转成img图像
** 1. HTMLCanvasElement.toDataURL() **
该方法可以把图片转换成base64格式信息,纯字符的图片表示法。
canvas.toDataURL(type, encoderOptions);
参数:type
可选。图片格式,默认为 image/png;encoderOptions
可选。在指定图片格式为 image/jpeg 或 image/webp的情况下,可以从 0 到 1 的区间内选择图片的质量。如果超出取值范围,将会使用默认值 0.92。其他参数会被忽略。
1 2 3 4 5 6 7 8
| var canvas = document.createElement('canvas'); canvas.setAttribute("id","canvas"); canvas.setAttribute("width","5"); canvas.setAttribute("height","5"); var dataURL = canvas.toDataURL(); console.log(dataURL);
|
** 2. HTMLCanvasElement.toBlob() **
该方法可以把canvas转换成Blob文件,通常用在文件上传中,因为是二进制的,对后端更加友好。
canvas.toBlob(callback, type, encoderOptions);
参数:type
可选。图片格式,默认为 image/png;encoderOptions
可选。在指定图片格式为 image/jpeg 或 image/webp的情况下,可以从 0 到 1 的区间内选择图片的质量。如果超出取值范围,将会使用默认值 0.92。其他参数会被忽略。
和toDataURL()
方法相比,toBlob()
方法是异步的,因此多了个callback参数,这个callback回调方法默认的第一个参数就是转换好的blob文件信息,本文demo的文件上传就是将canvas图片转换成二进制的blob文件,然后再ajax上传的,代码如下:
1 2 3 4 5 6 7 8
| canvas.toBlob(function (blob) { var xhr = new XMLHttpRequest(); xhr.open("POST", 'upload.php', true); xhr.send(blob); });
|
于是,经过“图片→canvas压缩→图片”三步曲,我们完成了图片前端压缩并上传的功能。
以下是完整代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
| var eleFile = document.querySelector("#imgfile");
var reader = new FileReader(), img = new Image();
var file = null;
var canvas = document.createElement('canvas'); var context = canvas.getContext('2d');
img.onload = function () { var originWidth = this.width; var originHeight = this.height; var maxWidth = 400, maxHeight = 400; var targetWidth = originWidth, targetHeight = originHeight; if (originWidth > maxWidth || originHeight > maxHeight) { if (originWidth / originHeight > maxWidth / maxHeight) { targetWidth = maxWidth; targetHeight = Math.round(maxWidth * (originHeight / originWidth)); } else { targetHeight = maxHeight; targetWidth = Math.round(maxHeight * (originWidth / originHeight)); } }
canvas.width = targetWidth; canvas.height = targetHeight; console.log(targetWidth + "|" + targetHeight); context.clearRect(0, 0, targetWidth, targetHeight); context.drawImage(img, 0, 0, targetWidth, targetHeight); var formData = new FormData(); formData.append("sessionid", $("#user_head_form #sessionid").val()); formData.append("host", $("#user_head_form input[name=host]").val()); formData.append("fileName", $("#user_head_form input[name=fileName]").val()); canvas.toBlob(function (blob) { $('#user_head_upload_box').hide(); $('#user_head_show_box').show(); formData.append("head", blob);
console.log(blob); $.ajax({ url: $("#user_head_form").attr("action"), type: 'POST', cache: false, data: formData, processData: false, contentType: false, dataType: "json", beforeSend: function () { console.log("before"); }, success: function (data) { if (data.code == 1) { console.log(data.data); $("#user_head_origin").attr("src", data.data); } else { console.log("Other"); } } }); }); };
reader.onload = function (e) { img.src = e.target.result; }; eleFile.addEventListener('change', function (event) { file = event.target.files[0]; if (file.type.indexOf("image") == 0) { reader.readAsDataURL(file); } });
|
*注:参考文章MDN HTMLCanvasElement.toBlob()、MDN HTMLCanvasElement.toDataURL()、HTML5 file API加canvas实现图片前端JS压缩并上传。