angularjs之手机端input图片上传(续)

来源:互联网 发布:满文翻译软件 编辑:程序博客网 时间:2024/09/21 09:26

为啥要写个续呢?解决一个问题:图片压缩

BTW,本文是针对ajax提交,如果本身就是form表单提交就不需要看了。

上一篇里说到h5可以用FileReader获取到图片信息,如base64,按道理这就可以传给服务端了,但是当图片很大的时候,这个字符串可能会写满好几张a4纸,这显然不合适,再者字符串太大服务端也接受不到- -于是发送之前压缩一下是个不错的选择,上代码:

 var zipPic=function (result) {      var canvas=document.getElementById("uploadImg");      var cxt=canvas.getContext('2d');      var img=new Image();      img.src= result;      canvas.width=640;      canvas.height=640*(img.height/img.width);      cxt.drawImage(img,0,0,640,canvas.height);      return canvas.toDataURL("image/jpeg",0.9); }

cxt.drawImage会将result所代表的图片绘制到canvas上去,并且重新指定了图片的宽高,
drawImage有3个方法:
在画布上定位图像:
context.drawImage(img,x,y);
在画布上定位图像,并规定图像的宽度和高度:
context.drawImage(img,x,y,width,height);
剪切图像,并在画布上定位被剪切的部分:
context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);
具体参数意思可以到w3school去看。

canvas.toDataURL就是压缩过后的base64,第一个参数是格式,有的时候传的图片时png什么的都可以转成jpg,第二个参数可以理解为画面质量,0~1,很好理解。

ok,到此为止,一切都很美好,然而……
以上方法在Android上都运行正常,然后在ios上toDataURL取到的却是空,百度之,发现ios自带canvas坑(以下摘自http://www.cnblogs.com/zhwl/p/4961473.html):
首先是图片的大小,如果图片的大小超过两百万像素,图片也是无法绘制到canvas上的,调用drawImage的时候不会报错,但是你用toDataURL获取图片数据的时候获取到的是空的图片数据。
再者就是canvas的大小有限制,如果canvas的大小大于大概五百万像素(即宽高乘积)的时候,不仅图片画不出来,其他什么东西也都是画不出来的。

应对第一种限制,处理办法就是瓦片绘制了。瓦片绘制,也就是将图片分割成多块绘制到canvas上,我代码里的做法是把图片分割成100万像素一块的大小,再绘制到canvas上。
应对第二种限制,我的处理办法是对图片的宽高进行适当压缩,我代码里为了保险起见,设的上限是四百万像素,如果图片大于四百万像素就压缩到小于四百万像素。四百万像素的图片应该够了,算起来宽高都有2000X2000了。

定义两个canvas:

    var canvas = document.createElement("canvas");    var ctx=canvas.getContext('2d');    var tCanvas = document.createElement("canvas");    var tctx = tCanvas.getContext("2d");代码片

压缩方法:

    //使用canvas对大图片进行压缩    function compress(img) {      var width = img.width;      var height = img.height;      //如果图片大于四百万像素,计算压缩比并将大小压至400万以下      var ratio;      if ((ratio = width * height / 4000000) > 1) {        ratio = Math.sqrt(ratio);        width /= ratio;        height /= ratio;      } else {        ratio = 1;      }      canvas.width = width;      canvas.height = height;      // 铺底色      ctx.fillStyle = "#fff";      ctx.fillRect(0, 0, canvas.width, canvas.height);      //如果图片像素大于100万则使用瓦片绘制      var count;      if ((count = width * height / 1000000) > 1) {        count = ~~(Math.sqrt(count) + 1); //计算要分成多少块瓦片      // 计算每块瓦片的宽和高        var nw = ~~(width / count);        var nh = ~~(height / count);        tCanvas.width = nw;        tCanvas.height = nh;        for (var i = 0; i < count; i++) {          for (var j = 0; j < count; j++) {            tctx.drawImage(img, i * nw * ratio, j * nh * ratio, nw * ratio, nh * ratio, 0, 0, nw, nh);            ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh);          }        }      } else {        ctx.drawImage(img, 0, 0, width, height);      }      //进行最小压缩      var ndata = canvas.toDataURL('image/jpeg', 0.1);      // console.log('压缩前:' + initSize);      // console.log('压缩后:' + ndata.length);      // console.log('压缩率:' + ~~(100 * (initSize - ndata.length) / initSize) + "%");      tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0;      return ndata;    }

压缩方法有了,还要注意一点就是调用的时候,我当时在这花了蛮久时间0.0

reader.onload = function (e) {            var result=this.result;            $scope.success.up = true;            var img=new Image();            img.src= result;            var maxsize = 100 * 1024;            if(result.length<=maxsize){              transferImgSrc=result;            }else {              if(img.complete){//一定要等图片加载完了再调压缩                callback();              }else {                img.onload=callback;              }              function callback() {                transferImgSrc = compress(img);//此处得到base64                img = null;              }            } }
0 0
原创粉丝点击