应用canvas缩小照片尺寸的方式示例

2021-02-22 17:47 jianzhan

难题来源于

这个难题,源于提交照片文档的情况下,后台管理限定了2MB的尺寸,but在调起照相机照相的情况下分分钟超出了2MB,以便不危害客户体验和作用要求,必须前端开发对尺寸开展缩小,随后传到后台管理。

思路剖析

找了许多材料,发现仅有canvas能够对照片开展缩小解决。

基本原理大约便是: 1、先将照片的file文档转成baseURL 2、建立1个image标识去接受文档获得照片的宽高和占比。 3、建立canvas画布设定画布的尺寸。 4、将照片绘图到canvas上面。 5、对canvas开展缩小解决,得到新的baseURL 6、将baseURL转换回文档。

前提条件的涵数

将file文档转换为base64

/**
* @param {2进制文档流} file 
* @param {回调函数涵数,回到base64} fn 
*/
function changeFileToBaseURL(file,fn){
  // 建立载入文档目标
      var fileReader = new FileReader();
      //假如file没界定回到null
      if(file == undefined) return fn(null);
      // 载入file文档,获得的結果为base64位
      fileReader.readAsDataURL(file);
      fileReader.onload = function(){
        // 把载入到的base64
        var imgBase64Data = this.result;
        fn(imgBase64Data);
      }
    }

将base64转换为文档流

/**
 * 将base64变换为文档
 * @param {baseURL} dataurl 
 * @param {文档名字} filename 
 * @return {文档2进制流}
*/
function dataURLtoFile(dataurl, filename) {
    var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
    while(n--){
        u8arr[n] = bstr.charCodeAt(n);
    }
    return new File([u8arr], filename, {type:mime});
 }

缩小方式

/**
* canvas缩小照片
* @param {主要参数obj} param 
* @param {文档2进制流} param.file 必传
* @param {总体目标缩小尺寸} param.targetSize 不传原始取值⑴
* @param {輸出照片宽度} param.width 不传原始取值⑴,等比放缩无需传高宽比
* @param {輸出照片名字} param.fileName 不传原始取值image
* @param {缩小照片水平} param.quality 不传原始取值0.92。值范畴0~1
* @param {回调函数涵数} param.succ 必传
*/
function pressImg(param){
  //假如沒有回调函数涵数就不实行
  if(param && param.succ){
     //假如file没界定回到null
     if(param.file == undefined) return param.succ(null);
     //给主要参数附原始值
     param.targetSize = param.hasOwnProperty("targetSize") ? param.targetSize : ⑴;
     param.width = param.hasOwnProperty("width") ? param.width : ⑴;
     param.fileName = param.hasOwnProperty("fileName") ? param.fileName: "image";
     param.quality = param.hasOwnProperty("quality") ? param.quality : 0.92;
     var _this = this;
     // 获得文档种类
     var fileType = param.file.type;
     // console.log(fileType) //image/jpeg
     if(fileType.indexOf("image") == ⑴){
       console.log('请挑选照片文档^_^');
       return param.succ(null);
     }
     //假如当今size比总体目标size小,立即輸出
     var size = param.file.size;
     if(param.targetSize > size){
       return param.succ(param.file);
     }
     // 载入file文档,获得的結果为base64位
     changeFileToBaseURL(param.file,function(base64){
       if(base64){
         var image = new Image();
         image.src = base64;
         image.onload = function(){
           // 得到长宽占比
           var scale = this.width / this.height;
           // console.log(scale);
           //建立1个canvas
           var canvas = document.createElement('canvas');
           //获得左右文
           var context = canvas.getContext('2d');
           //获得缩小后的照片宽度,假如width为⑴,默认设置原图宽度
           canvas.width = param.width == ⑴ ? this.width : param.width;
           //获得缩小后的照片高宽比,假如width为⑴,默认设置原图高宽比
           canvas.height = param.width == ⑴ ? this.height : parseInt(param.width / scale);
           //把照片绘图到canvas上面
           context.drawImage(image, 0, 0, canvas.width, canvas.height);
           //缩小照片,获得到新的base64Url
           var newImageData = canvas.toDataURL(fileType,param.quality);
           //将base64转换成文档流
           var resultFile = dataURLtoFile(newImageData,param.fileName);
           //分辨假如targetSize比较有限制且缩小后的照片尺寸比总体目标尺寸大,就弹错误误
           if(param.targetSize != ⑴ && param.targetSize < resultFile.size){
             console.log("照片提交规格太大,请再次提交^_^");
             param.succ(null);
           }else{
             //回到文档流
             param.succ(resultFile);
           }
         }
       }
     });
   }
 }

方式应用

文档的size是依照字节,因此大家必须把规定的尺寸转换成字节。 1字节便是1byte便是1B,1KB = 1024B,1MB = 1024 * 1024B

<input type="file" id="fileImg" class="fileImg"/>
// 照片文档提交获得url
$("#fileImg").on('change',function(){
   pressImg({
     file:this.files[0],
     targetSize:2 * 1024 * 1024,
     quality:0.5,
     width:600,
     succ:function(resultFile){
         //假如并不是null便是缩小取得成功
         if(resultFile){
           //TODO
        }
     }
  })
});

难题总结

 照片缩小水平

照片的缩小水平不大好明确,因此能够开展数次尝试,依据要求方的规定开展调剂。 更改总体目标照片的尺寸和清楚度都可以以更改照片的缩小水平。

原本想做1个缩小照片的递归,直至照片尺寸合乎期待

后来发现

  • 假如总体目标尺寸较为小,照片怎样开展缩小都不可以考虑标准的情况下,会导致循环系统没法跳出来,消耗資源。
  • 假如照片开展几回缩小以后,文档尺寸不容易更改了,有的情况下还会提升,奇怪异怪。 因此就舍弃了递归。

ios拍攝方位难题

由于ios调起系统软件照相机照相是逆时针转动了90度。 而在我缩小照片以后传到后台管理,发现照片的exif信息内容的拍攝方位遗失,致使ios提交的照片全是逆时针转动了90度。这个难题安卓系统不曾发现。

现阶段一些怀疑,是base64转换成file文档的情况下,遗失的。 以后认证后会在这里开展填补表明。

@version1.0——2019⑻⑵——建立《应用canvas缩小照片尺寸》

©burning_韵77

以上便是本文的所有內容,期待对大伙儿的学习培训有一定的协助,也期待大伙儿多多适用脚本制作之家。