前端压缩的意义
对于大尺寸图片的上传, 如头像等, 在前端进行压缩除了省流量外,最大的意义是提高了上传速度, 改善了用户体验。
以下例子可作为一个头像上传压缩, 图片被压缩至长宽最大小于200px。
实现原理
核心API使用canvas
的drawImage()
方法。
canvas
的drawImage()
方法API如下:
context.drawImage(img, dx, dy); context.drawImage(img, dx, dy, dWidth, dHeight); context.drawImage(img, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
原理代码如下
var canvas = document.createElement('canvas'); var context = canvas.getContext('2d'); canvas.width = 200; canvas.height = 200; // 核心JS就这个 context.drawImage(img,0,0,200,200);
图片呈现在浏览器
HTML5 file API可以让图片在上传之前直接在浏览器中显示,通常使用FileReader
方法,代码示意如下:
var reader = new FileReader(), img = new Image(); // 读文件成功的回调 reader.onload = function(e) { // e.target.result就是图片的base64地址信息 img.src = e.target.result; }; eleFile.addEventListener('change', function (event) { reader.readAsDataURL(event.target.files[0]); });
于是,包含图片信息的context.drawImage()
方法中的img
图片就有了。
把canvas画布转换成img图像
- canvas.toDataURL()方法
- 语法如下:
canvas.toDataURL(mimeType, qualityArgument)
可以把图片转换成base64格式信息,纯字符的图片表示法。
canvas.toBlob()方法语法如下:
canvas.toBlob(callback, mimeType, qualityArgument)
可以把canvas转换成Blob文件,通常用在文件上传中,因为是二进制的,对后端更加友好。
完整代码如下:
<!doctype html> <html> <head> <title>前端压缩</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body> <input id="file" type="file"> <img id="img"> <script type="text/javascript"> var eleFile = document.querySelector('#file'); // 压缩图片需要的一些元素和对象 var reader = new FileReader(), img = new Image(); // 选择的文件对象 var file = null; // 缩放图片需要的canvas var canvas = document.createElement('canvas'); var context = canvas.getContext('2d'); // base64地址图片加载完毕后 img.onload = function() { // 图片原始尺寸 var originWidth = this.width; var originHeight = this.height; // 最大尺寸限制 var maxWidth = 200, maxHeight = 200; // 目标尺寸 var targetWidth = originWidth, targetHeight = originHeight; // 图片尺寸超过400x400的限制 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对图片进行缩放 canvas.width = targetWidth; canvas.height = targetHeight; // 清除画布 context.clearRect(0, 0, targetWidth, targetHeight); // 图片压缩 context.drawImage(img, 0, 0, targetWidth, targetHeight); // canvas转为blob并上传 canvas.toBlob(function(blob) { var eleLink = document.createElement('a'); eleLink.download = '压缩'; eleLink.style.display = 'none'; eleLink.href = URL.createObjectURL(blob); document.getElementById('img').src = eleLink.href; // 触发点击 document.body.appendChild(eleLink); eleLink.click(); // 然后移除 // document.body.removeChild(eleLink); }, file.type || 'image/png'); }; // 文件base64化,以便获知图片原始尺寸 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); } }); </script> </body> </html>
本文链接地址: 前端图片压缩基于(h5 file API & canvas)