blob的理解与canvas压缩图片上传

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就是利用canvasdrawImage()方法,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表示导出的图片质量,只要导出为jpgwebp格式的时候此参数才有效果,默认值是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);
            }
        });
    });
这就是被压缩的图片,原图是1024*727的尺寸

所以总体的思路就是获取到上传的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/

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容