Blob是什么?
HTML5中的Blob对象除了存放二进制数据外还可以设置这个数据的MINE
类型,这相当于对文件的储存,其它很多二进制对象也是从这个对象继承的。
var data='<b id="content" style="font-size:32px;color:red;">次碳酸钴</b>';
var blob=new Blob([data],{"type":"text/html"})
console.log(blob)
这样我们就创建了一个Blob对象,第一个参数是一个数组,也必须是一个数组,第二个参数是对这个Blol对象的配置属性,目前就一个type也就是相关的MIME需要设置。然后可以创建出一个
URL
来访问它,使用URL
对象的createObjectURL
方法
var data='<b id="content" style="font-size:32px;color:red;">次碳酸钴</b>';
var blob=new Blob([data],{"type":"text/html"})
console.log(blob)
window.onload=function(){
var iframe=document.createElement("iframe");
iframe.src=URL.createObjectURL(blob);
document.body.appendChild(iframe);
};
然后页面的显示
<iframe src="blob:http://localhost:8080/ccbb2543-0b24-410a-914c-89c2ec655d77"></iframe>
<iframe>
标签就是就是在页面中重新再开辟一个地方,插入新的html,src
属性就是链接。
iframe 的优缺点
优点:
重载页面时不需要重载整个页面,只需要重载页面中的一个框架页(减少数据的传输,减少网页的加载时间);
技术简单,使用方便,主要应用于不需要搜索引擎来搜索的页面;
方便开发,减少代码的重复率(比如页面的header,footer);
缺点:
会产生很多的页面,不易于管理;
不易打印;
多框架的页面会增加服务气得http请求;
浏览器的后退按钮无效等;
而我bb这里多我其实就是想写用canvas压缩图片上传 上面部分是了解一下Blob,下面才是重点
canvas压缩图片的核心API就是利用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);
对于本文例子的压缩 只需要用到五个参数。举个例子,一张图片(假设图片对象是img)的原始尺寸是40003000,现在需要把尺寸限制为400300大小,很简单,原理如下代码示意:
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
canvas.width = 400;
canvas.height = 300;
// 核心JS就这个
context.drawImage(img,0,0,400,300);//意思就是 从左上角0 0开始绘制一个宽度为400高度为300的canvas
所以 canvas
的代码写了,我们就需要处理图片来源和图片去向两个问题
1.如何把系统中的图片呈现到浏览器上?
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就有啦
2.canvas只是一块画布,那么如何把转换成img显示呢?
canvas
提供了两个2D转换为图片的方法:canvas.toDataURL()
和canvas.toBlob()
canvas.toDataURL()方法
canvas.toDataURL(mimeType, qualityArgument)
可以把图片转换成base64
格式信息,纯字符的图片表示法。
mimeType
表示canvas导出来的base64
图片的类型,默认是png
格式,也即是默认值是'image/png'
,我们也可以指定为jpg
格式'image/jpeg'
或者webp
等格式。file
对象中的file.type
就是文件的mimeType
类型,在转换时候正好可以直接拿来用(如果有file对象)。qualityArgument
表示导出的图片质量,只要导出为jpg
和webp
格式的时候此参数才有效果,默认值是0.92
,是一个比较合理的图片质量输出参数,通常情况下,我们无需再设定。
canvas.toBlob()方法
canvas.toBlob(callback, mimeType, qualityArgument)
这个方法相比之前的方法的好处是异步
,所以有一个callback
回调。这个callback
回调方法默认的第一个参数就是转换好的blob文件信息,本文demo的文件上传就是将canvas图片转换成二进制
的blob文件,然后再ajax上传的,代码如下:
// canvas转为blob并上传
canvas.toBlob(function (blob) {
// 图片ajax上传
var xhr = new XMLHttpRequest();
// 开始上传
xhr.open("POST", 'upload.php', true);
xhr.send(blob);
});
所以 压缩的三个步骤就是:图片-》canvas压缩-》图片
完整代码:
HTML代码
<div>
<input id="file" type="file">
<img src=""/>
</div>
JS代码
$(document).ready(function(){
var eleFile=document.getElementById('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;
//最大尺度的尺寸限制在 400*400
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对图片进行缩放
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) {//blob将base64编码的src 以二进制的形式存进了 Blob对象
$('img').attr('src',window.URL.createObjectURL(blob) )//这样可以在页面上形成一个预览的效果
// $('img').attr('src',HTMLMediaElement.srcObject(blob))//这个方法是MDN说会替代上面的方法 但是我在浏览器中使用还不支持(什么鬼???)
// 图片ajax上传-》将blob二进制数据上传上去
console.log(blob)
}, file.type || 'image/png');
}
// 文件base64化,以便获知图片原始尺寸
reader.onload = function(e) {
img.src = e.target.result;//base64编码的src
//通过编码之后
};
eleFile.addEventListener('change', function (event) {
file = event.target.files[0];
// 选择的文件是图片
if (file.type.indexOf("image") == 0) {
reader.readAsDataURL(file);
}
});
});
所以总体的思路就是获取到上传的img,通过
canvas
压缩之后,再传给后台,压缩之后放在页面形成一个预览效果,也就是用到window.URL.createObjectURL(blob)
方法。其中最为关键的就是 如果原始的宽度大于高度(就需要用高度除以宽度的比例来缩放高度),反之一样。
本文涉及的几个重要API
window.URL.createObjectURL()
静态方法会创建一个 DOMString
,其中包含一个表示参数中给出的对象的URL。这个 URL 的生命周期和创建它的窗口中的 document
绑定。这个新的URL 对象表示指定的 File
对象或 Blob
对象。简单的理解就是,可以在页面上预览本地上传的图片或者视频(将blob对象直接赋值给vedio
标签,而不是source
)
reader.readAsDataURL()
通过这个API可以从浏览器中异步访问文件系统中的数据,结果用data:url的字符串形式表示。因此,FileReader
接口可以读取文件中的数据,并将读取的数据放入到内存中去。通过FileReader
接口中的readAsDataURL()
方法可以获取API异步读取的文件数据,另存为数据URL;将该URL绑定到img
标签的src
属性上,就可以实现图片的上传预览效果了。
new FileReader()
FileReader主要用于将文件内容读入内存,通过一系列异步接口,可以在主线程中访问本地文件。
参考地址:https://www.zhangxinxu.com/wordpress/2017/07/html5-canvas-image-compress-upload/