本篇主要实现
- 前端回显上传图片
- 前端压缩上传图片质量
主要使用技术
- window.URL.createObjectURL
- FileReader
- 滤镜IE9以下
- html5 canvas
代码如下
- index.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8" />
<title>图片上传-前端回显图片-模拟图片选择控件-前端压缩</title>
<style>
</style>
<script type="text/javascript" src="index.js"></script>
</head>
<body>
<!-- 隐藏 file input控件 -->
<!-- 方法1:style="width:0;height:0;" 兼容ie9 ie9-,其他浏览器可以设置为display:none -->
<!-- 方法2:style="position:fixed;left:-99999px;" 移出显示区域 -->
<input type="file" name="file" style="position:fixed;left:-99999px;" accept="image/jpg,image/jpeg,image/png" onchange="picPreview(this)" />
<div onclick="selectPic()" style="width:541px; height:361px; border: 1px solid black;">
<img id="preview" style="display:block;" width="540" height="360" alt="点击选择图片" />
</div>
<div>压缩后展示:</div>
</body>
</html>
- index.js
var selectPic = function(imgPreview) {
// 点击选择图片后出发input file的click事件
document.getElementsByName("file")[0].click();
}
var picPreview = function(imgObj) {
var accepts = imgObj.accept;
// chrome63 选择上传图片后,再次点击浏览,但不选择图片,会导致上次选择的内容被清除
try {
if(imgObj.files.length == 0) {
return;
}
var suffix = getSuffix(imgObj.files[0].name);
// firefox5.0 不支持 str.startsWith,因此使用indexOf判断
if (!imgObj.files[0] || -1 == accepts.indexOf(suffix)) {
alert("请重新选择图片,格式应为" + accepts);
imgObj.outerHTML = imgObj.outerHTML;// 重新初始化img,即清除已选择的文件
document.getElementById("preview").src = "";// 清空预览图
return;
}
// https://developer.mozilla.org/zh-CN/docs/Web/API/Window/URL
window.URL = window.URL || window.webkitURL;
var imgSrc = window.URL.createObjectURL(imgObj.files[0]);
document.getElementById("preview").src = imgSrc;
// FileReader
var freader = new FileReader();
freader.readAsDataURL(imgObj.files[0]);
freader.onload = function(e) {
document.getElementById("preview2").src = e.target.result;
};
var oldSize = imgObj.files[0].size;
console.log("原文件大小: " + imgObj.files[0].size);
var canvas = document.createElement("canvas");
var imgtype = "image/jpeg";//image/png, image/jpg 压缩效果不如意
var cps = 0.34; //质量
if (canvas.getContext) {// 支持canvas,可以做压缩图片(质量压缩,分辨率不变(宽*高))
document.getElementById("preview").onload = function() {
var w = this.naturalWidth;
var h = this.naturalHeight;
canvas.width = w;
canvas.height = h;
var d2 = canvas.getContext("2d");
d2.clearRect(0, 0, w, h);
d2.drawImage(this, 0, 0);
// 仅 image/jpeg 和 image/webp 格式,质量参数才有效(才能压缩图片质量)
// webp 格式 仅 chrome 支持
// 1 压缩为base64 字符串
var dataURL = canvas.toDataURL(imgtype, cps);
console.log("canvas.toDataURL的大小:" + dataURL.length + ", 压缩比:" + dataURL.length/oldSize);
// 文件上传 dataURL
var newdiv = document.createElement("div");
newdiv.style = "min-width: 500px; min-height: 1500px; ";
document.body.appendChild(newdiv);
var newimg = new Image();
newimg.src = dataURL;
newdiv.appendChild(newimg);
var toblob = convertImgDataToBlob(dataURL);
console.log("dataURL to blob的大小:" + toblob.size + ", 压缩比:" + toblob.size/oldSize);
// 2 压缩为二进制blob对象
canvas.toBlob(function(blob){
console.log("canvas.toBlob的大小 " + blob.size + ", 压缩比:" + blob.size/oldSize);
//文件上传 blob
}, imgtype, cps);
};
}
} catch (e) {
console.log(e);
if (!imgObj.value) {
return;
}
// not support input-files.files, such as ie9 ie9-
// select & blur 解决ie9无法直接访问图片
imgObj.select();
imgObj.blur();// IE9以下,如果file控件获得焦点,则document.selection.createRange()拒绝访问
// 使用滤镜
var path = document.selection.createRange().text;
if (-1 == accepts.indexOf(getSuffix(path))) {
alert("请选择图片");
imgObj.outerHTML = imgObj.outerHTML;// 重新初始化img,即清除已选择的文件
// 清空滤镜,清空预览图
document.getElementById("previewOnIe9").src = "";
document.getElementById("previewOnIe9").style.filter = "";
return;
}
document.getElementById("previewOnIe9").style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=scale);";
document.getElementById("previewOnIe9").filters
.item("DXImageTransform.Microsoft.AlphaImageLoader").src = document.selection
.createRange().text;
// 设置img的src为base64编码的透明图片 取消显示浏览器默认图片
document.getElementById("previewOnIe9").src = "data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==";
}
}
function convertImgDataToBlob(base64Data) {
var format = "image/jpeg";
var base64 = base64Data;
var code = window.atob(base64.split(",")[1]);
var aBuffer = new window.ArrayBuffer(code.length);
var uBuffer = new window.Uint8Array(aBuffer);
for (var i = 0; i < code.length; i++) {
uBuffer[i] = code.charCodeAt(i) & 0xff;
}
var blob = null;
try {
blob = new Blob([ uBuffer ], {type: format});
}
catch (e) {
window.BlobBuilder = window.BlobBuilder ||
window.WebKitBlobBuilder ||
window.MozBlobBuilder ||
window.MSBlobBuilder;
if (e.name == 'TypeError' && window.BlobBuilder) {
var bb = new window.BlobBuilder();
bb.append(uBuffer.buffer);
blob = bb.getBlob("image/jpeg");
}
else if (e.name == "InvalidStateError") {
blob = new Blob([ aBuffer ], {type: format});
}
else {
}
}
return blob;
};
var getSuffix = function(name) {
var suffix = null;
var index;
if ((index = name.lastIndexOf(".")) != -1) {
suffix = name.substring(index + 1);
}
return suffix;
}