最近项目中需要用到图片上传,但是目前照片拍的或者扫描的都会很大,直接上传到服务器会出现图片太大,文件打影响上传速度,还有如果图片的分辨率过大的话查看也是问题。因此想到了在前端利用html5 Canvas技术进行图片压缩后上传。不过压缩问题解决后又有问题了,客户端一般图片通过拍照或扫描会出现图片需要旋转后才能查看,因此想到了如果先把图片进行自定义旋转然后对此图片压缩上传。
参考了网上一些文章搞出了此功能
http://qings.blog.51cto.com/4857138/997998/
http://www.cnblogs.com/hutuzhu/p/5265023.html
http://leonshi.com/demo/canvas-compressor.html
下面就讲下具体实现方法吧
利用FileReader在图片载入的时候先将图片压缩提供预览,由于图片大小不一定,因此可以设置图片默认分辨率比例比如800*1000,有可能图片长宽都小于此设置值,因此要根据长宽的实际值与设置值的比例来确定具体采用哪个比例换算。图片旋转只能对原图做操作,这样才能保证旋转后按原图和设置值的比例重新压缩。
代码:
var canvas = document.getElementById('canvas');
var source = document.getElementById('source');
var preview = document.getElementById('preview');
var dataUrl;//图片压缩后路径
var qualityLevel = 0.8;
$(function () {
$('#single').on('change', function (e) {
var img = e.target.files[0]
var reader = new FileReader();
reader.readAsDataURL(img);
reader.onload = function (e) { // reader onload start
var url = reader.result;
source.src = url;
} // reader onload end
reader.readAsDataURL(img);
})
})
source.onload = function () {
var width = source.width;
var height = source.height;
var context = canvas.getContext('2d');
var newwidth = 800;
var newheight = 1000;
canvas.width = newwidth;
canvas.height = newheight;
//当宽度和高度都小于设置值
if (width <= newwidth && height <= newheight) {
newwidth = width;
newheight = height;
}
//当宽度小于设置值高度大于设置值按高度比例调整
if (width <= newwidth && height > newheight) {
newwidth = newheight / height * width;
}
//当宽度大于设置值高度小于设置值案宽度比例调整
if (width > newwidth && height <= newheight) {
newheight = newwidth / width * height;
}
//当宽度和高度都大于设置值
if (width > newwidth && height > newheight) {
var bla = newwidth / width;
var blb = newheight / height;
if (bla > blb) {
newwidth = width * blb;
newheight = height * blb
}
else {
newwidth = width * bla;
newheight = height * bla;
}
}
var sx = 0;
var sy = 0;
var sWidth = width;
var sHeight = height;
var dx = 0;
var dy = 0;
var dWidth = newwidth;
var dHeight = newheight;
$("#detail").html("W:" + sWidth + " H:" + sHeight)
context.drawImage(source, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
dataUrl = canvas.toDataURL('image/jpeg', qualityLevel);
//preview.src = dataUrl;
};
function compress(pid) {
var source = document.getElementById("pic_" + pid);
var width = source.width;
var height = source.height;
var context = canvas.getContext('2d');
var newwidth = 800;
var newheight = 1000;
canvas.width = newwidth;
canvas.height = newheight;
//当宽度和高度都小于设置值
if (width <= newwidth && height <= newheight) {
newwidth = width;
newheight = height;
}
//当宽度小于设置值高度大于设置值按高度比例调整
if (width <= newwidth && height > newheight) {
newwidth = newheight / height * width;
}
//当宽度大于设置值高度小于设置值案宽度比例调整
if (width > newwidth && height <= newheight) {
newheight = newwidth / width * height;
}
//当宽度和高度都大于设置值
if (width > newwidth && height > newheight) {
var bla = newwidth / width;
var blb = newheight / height;
if (bla > blb) {
newwidth = width * blb;
newheight = height * blb
}
else {
newwidth = width * bla;
newheight = height * bla;
}
}
var sx = 0;
var sy = 0;
var sWidth = width;
var sHeight = height;
var dx = 0;
var dy = 0;
var dWidth = newwidth;
var dHeight = newheight;
$("#detail").html("W:" + sWidth + " H:" + sHeight)
context.drawImage(source, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
dataUrl = canvas.toDataURL('image/jpeg', qualityLevel);
//preview.src = dataUrl;
}
var quality = document.getElementById('quality');
quality.addEventListener('keydown', function (e) {
if (e.which === 13) {
var value = e.currentTarget.value;
value = value < 1 ? 1 : value;
value = value > 100 ? 100 : value;
qualityLevel = parseFloat(value / 100);
document.getElementById('level').innerText = qualityLevel;
source.onload();
}
}, false);
function rotateImg(pid, direction) {
//最小与最大旋转方向,图片旋转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');
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;
}
compress('source');
}
demo下载