前端压缩的意义
对于大尺寸图片的上传, 如头像等, 在前端进行压缩除了省流量外,最大的意义是提高了上传速度, 改善了用户体验。
以下例子可作为一个头像上传压缩, 图片被压缩至长宽最大小于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)