cropper.js 实现HTML5 裁剪图片并上传(裁剪上传头像。)

时间:2024-04-16 16:28:19

 https://blog.****.net/qq727013465/article/details/51823231

我的需求功能:在手机端实现上传头像,带裁剪框。

cropper.js  通过canvas实现图片裁剪,最后在通过canvas获取裁剪区域的图片base64串。

cropper 文档:官方文档是全英文的,好吧我看不懂。只能一个个试试效果,就有了下面的总结。官方文档<-点这

1.container 容器   2.canvas 图片   3.crop  裁剪框

option相关参数说明:

 

viewMode 显示模式

  • Type: Number
  • Default: 0
  • Options:
    • 0: the crop box is just within the container    裁剪框只能在 1内移动
    • 1: the crop box should be within the canvas   裁剪框 只能在  2图片内移动
    • 2: the canvas should not be within the container  2图片 不全部铺满1 (即缩小时可以有一边出现空隙)
    • 3: the container should be within the canvas  2图片 全部铺满1 (即 再怎么缩小也不会出现空隙)

dragMode  拖动模式

  • Default: \'crop\'
  • Options:
    • \'crop\': create a new crop box  当鼠标 点击一处时根据这个点重新生成一个 裁剪框
    • \'move\': move the canvas    可以拖动图片
    • \'none\': do nothing  图片就不能拖动了

Define the dragging mode of the cropper.

toggleDragModeOnDblclick   默认true .是否允许 拖动模式 “crop” 跟“move” 的切换状态。。即当点下为crop 模式,如果未松开拖动这时就是“move”模式。放开后又为“crop”模式

preview  截图的显示位置   型:String(jQuery选择器),默认值\'\'
responsive :类型:Boolean,默认值true。是否在窗口尺寸改变的时候重置cropper。

 

checkImageOrigin:类型:Boolean,默认值true。默认情况下,插件会检测图片的源,如果是跨域图片,图片元素会被添加crossOrigin class,并会为图片的url添加一个时间戳来使getCroppedCanvas变为可用。添加时间戳会使图片重新加载,以使跨域图片能够使用getCroppedCanvas。在图片上添加crossOrigin class会阻止在图片url上添加时间戳,及图片的重新加载。

background:类型:Boolean,默认值true。是否在容器上显示网格背景。 要想改背景,我是直接改,cropper.css样式中的 cropper-bg

canvas(图片)相关
movable:类型:Boolean,默认值true。是否允许移动图片
rotatable:类型:Boolean,默认值true。是否允许旋转图片。
scalable  默认 true 。 是否允许扩展图片。(暂时不知道干嘛用)
zoomable 默认true, 石头允许缩放图片。
zoomOnWheel 默认 true 是否允许鼠标滚轴 缩放图片
zoomOnTouch 默认true 是否允许触摸缩放图片(触摸屏上两手指操作。)
wheelZoomRatio 默认0.1 师表滚轴缩放图片比例。即滚一下。图片缩放多少。如 0.1 就是图片的10%
 
crop(裁剪框)相关

aspectRatio 裁剪框比例  默认NaN   例如:: 1 / 1,//裁剪框比例 1:1

modal:类型:Boolean,默认值true。是否在剪裁框上显示黑色的模态窗口。
cropBoxMovable :默认true ,是否允许拖动裁剪框cropBoxResizable :默认 true,//是否允许拖动 改变裁剪框大小
autoCrop:类型:Boolean,默认值true。是否允许在初始化时自动出现裁剪框。autoCropArea:类型:Number,默认值0.8(图片的80%)。0-1之间的数值,定义自动剪裁框的大小。highlight:类型:Boolean,默认值true。是否在剪裁框上显示白色的模态窗口。
guides:类型:Boolean,默认值true。是否在剪裁框上显示虚线。
center:  默认true  是否显示裁剪框 中间的+ 

restore :  类型:Boolean,默认值true  是否调整窗口大小后恢复裁剪区域。

大小相关
minContainerWidth:类型:Number,默认值200。容器的最小宽度。minContainerHeight:类型:Number,默认值100。容器的最小高度。minCanvasWidth:类型:Number,默认值0。canvas 的最小宽度(image wrapper)。minCanvasHeight:类型:Number,默认值0。canvas 的最小高度(image wrapper)。监听触发的方法build:类型:Function,默认值nullbuild.cropper事件的简写方式。 ====== 。控件初始化前执行built:类型:Function,默认值nullbuilt.cropper事件的简写方式。  ====== 空间初始化完成后执行dragstart:类型:Function,默认值nulldragstart.cropper事件的简写方式。 ======  拖动开始执行dragmove:类型:Function,默认值nulldragmove.cropper事件的简写方式。======  拖动移动中执行dragend:类型:Function,默认值nulldragend.cropper事件的简写方式。======  拖动结束执行zoomin:类型:Function,默认值nullzoomin.cropper事件的简写方式。 ======  缩小执行zoomout:类型:Function,默认值nullzoomout.cropper事件的简写方式。 ======  放大执行

 

demo 下载 

 

html  

 

[html] view plain copy
 
  1. <section style="margin-top: 50px;">  
  2.         <input id="photoBtn" type="button" onclick="document.getElementById(\'inputImage\').click()" value="选择照片"><!-- 可以增加自己的样式 -->  
  3.         <input  id="inputImage"  type="file" accept="image/*" style="display: none;"/>  
  4.         <br/>  
  5.         <img  id="showImg" />  
  6.     </section>  
  7.   
  8.     <div class="container" style="padding: 0;margin: 0;position:fixed;display: none;top: 0;left: 0;z-index: 200;" id="containerDiv">  
  9.         <div class="row" style="display: none;" id="imgEdit">  
  10.           <div class="col-md-9">  
  11.             <div class="img-container">  
  12.               <img src="" alt="Picture">  
  13.             </div>  
  14.           </div>  
  15.         </div>  
  16.         <div class="row" id="actions" style="padding: 0;margin: 0;width: 100%;position: fixed;bottom: 5px;">  
  17.           <div class="col-md-9 docs-buttons">  
  18.             <div class="btn-group" >  
  19.               <button type="button" class="btn btn-primary" data-method="destroy" title="Destroy" style="height: auto;">  
  20.                 <span class="docs-tooltip" data-toggle="tooltip" >  
  21.                   <span class="fa fa-power-off" >取消</span>  
  22.                 </span>  
  23.               </button>  
  24.             </div>  
  25.       
  26.             <div class="btn-group btn-group-crop " style="float: right;">  
  27.               <button type="button" class="btn btn-primary" id="imgCutConfirm" data-method="getCroppedCanvas" data-option="{ "width": 320, "height": 180 }" style="height: auto;margin-right: 17px;">  
  28.                 <span class="docs-tooltip" data-toggle="tooltip" title="">确认</span<!--cropper.getCroppedCanvas({ width: 320, height: 180 }) -->  
  29.               </button>  
  30.             </div>  
  31.       
  32.           </div><!-- /.docs-buttons -->  
  33.         </div>  
  34.     </div>  
[html] view plain copy
 
  1. </pre><pre name="code" class="html">  

 

 

 使用调用cropper 截图   的js 

 

[html] view plain copy
 
  1. var fileImg = "";  
[html] view plain copy
 
  1. </pre><pre name="code" class="html">window.onload = function () {  
  2.   
  3.   \'use strict\';//表示强规则  
  4.     
  5.   var screenWidth = $(window).width();  
  6.   var screenHeight =  $(window).height();  
  7.      
  8.   var Cropper = window.Cropper;  
  9.   var console = window.console || { log: function () {} };  
  10.   var container = document.querySelector(\'.img-container\');  
  11.   var image = container.getElementsByTagName(\'img\').item(0);  
  12.   var actions = document.getElementById(\'actions\');  
  13.   var isUndefined = function (obj) {  
  14.       return typeof obj === \'undefined\';  
  15.   };  
  16.   var options = {  
  17.         minContainerHeight :  screenHeight,  
  18.         minContainerWidth : screenWidth,  
  19.         aspectRatio: 1 / 1,//裁剪框比例 1:1  
  20.         viewMode : 1,//显示  
  21.         guides :false,//裁剪框虚线 默认true有  
  22.         dragMode : "move",  
  23.         build: function (e) { //加载开始  
  24.             //可以放你的过渡 效果  
  25.         },  
  26.         built: function (e) { //加载完成  
  27.             $("#containerDiv").show();  
  28.             $("#imgEdit").show();  
  29.         },  
  30.         zoom: function (e) {  
  31.           console.log(e.type, e.detail.ratio);  
  32.         },  
  33.         background : true,// 容器是否显示网格背景  
  34.         movable : true,//是否能移动图片  
  35.         cropBoxMovable :false,//是否允许拖动裁剪框  
  36.         cropBoxResizable :false,//是否允许拖动 改变裁剪框大小  
  37.   };  
  38.   var cropper = new Cropper(image, options);  
[html] view plain copy
 
  1.  //禁用默认方法  
  2.   function preventDefault(e) {  
  3.     if (e) {  
  4.       if (e.preventDefault) {  
  5.         e.preventDefault();  
  6.       } else {  
  7.         e.returnValue = false;  
  8.       }  
  9.     }  
  10.   }  
  11.   
  12.   // Tooltip  
  13.   $(\'[data-toggle="tooltip"]\').tooltip();  
  14.   
  15.   
  16.   if (typeof document.createElement(\'cropper\').style.transition === \'undefined\') {  
  17.       $(\'button[data-method="rotate"]\').prop(\'disabled\', true);  
  18.       $(\'button[data-method="scale"]\').prop(\'disabled\', true);  
  19.   }  
  20.   
  21.   // Methods  
  22.   actions.querySelector(\'.docs-buttons\').onclick = function (event) {  
  23.     var e = event || window.event;  
  24.     var target = e.target || e.srcElement;  
  25.     var result;  
  26.     var input;  
  27.     var data;  
  28.   
  29.     if (!cropper) {  
  30.       return;  
  31.     }  
  32.   
  33.     while (target !== this) {  
  34.       if (target.getAttribute(\'data-method\')) {  
  35.         break;  
  36.       }  
  37.   
  38.       target = target.parentNode;  
  39.     }  
  40.   
  41.     if (target === this || target.disabled || target.className.indexOf(\'disabled\') > -1) {  
  42.       return;  
  43.     }  
  44.   
  45.     data = {  
  46.       method: target.getAttribute(\'data-method\'),  
  47.       target: target.getAttribute(\'data-target\'),  
  48.       option: target.getAttribute(\'data-option\'),  
  49.       secondOption: target.getAttribute(\'data-second-option\')  
  50.     };  
  51.   
  52.     if (data.method) {  
  53.       if (typeof data.target !== \'undefined\') {  
  54.         input = document.querySelector(data.target);  
  55.   
  56.         if (!target.hasAttribute(\'data-option\') && data.target && input) {  
  57.           try {  
  58.             data.option = JSON.parse(input.value);  
  59.           } catch (e) {  
  60.             console.log(e.message);  
  61.           }  
  62.         }  
  63.       }  
  64.   
  65.       if (data.method === \'getCroppedCanvas\') {  
  66.         data.option = JSON.parse(data.option);  
  67.       }  
  68.   
  69.       result = cropper[data.method](data.option, data.secondOption);  
  70.   
  71.       switch (data.method) {  
  72.         case \'scaleX\':  
  73.         case \'scaleY\':  
  74.           target.setAttribute(\'data-option\', -data.option);  
  75.           break;  
  76.   
  77.         case \'getCroppedCanvas\':  
  78.           if (result) {  
  79.                 
  80.             fileImg = result.toDataURL(\'image/jpg\');  
  81.             $("#showImg").attr("src",fileImg).show();  
  82.             $("#photoBtn").val("重新选择");  
  83.           }  
  84.   
  85.           break;  
  86.   
  87.         case \'destroy\':  
  88.             $("#inputImage").val("");  
  89.             $("#containerDiv").hide();  
  90.             $("#imgEdit").hide();  
  91.           break;  
  92.       }  
  93.   
  94.       if (typeof result === \'object\' && result !== cropper && input) {  
  95.         try {  
  96.           input.value = JSON.stringify(result);  
  97.         } catch (e) {  
  98.           console.log(e.message);  
  99.         }  
  100.       }  
  101.   
  102.     }  
  103.   };  
  104.   
  105.   // Import image  
  106.   var inputImage = document.getElementById(\'inputImage\');  
  107.   var URL = window.URL || window.webkitURL;  
  108.   var blobURL;  
  109.   
  110.   if (URL) {  
  111.     inputImage.onchange = function () {  
  112.       var files = this.files;  
  113.       var file;  
  114.   
  115.       if (cropper && files && files.length) {  
  116.         file = files[0];  
  117.   
  118.         if (/^image\/\w+/.test(file.type)) {  
  119.           blobURL = URL.createObjectURL(file);  
  120.           cropper.reset().replace(blobURL);  
  121.         } else {  
  122.           window.alert(\'Please choose an image file.\');  
  123.         }  
  124.       }  
  125.       $(inputImage).find("img").hide();  
  126.     };  
  127.   } else {  
  128.     inputImage.disabled = true;  
  129.     inputImage.parentNode.className += \' disabled\';  
  130.   }  
  131.   
  132. };  
[html] view plain copy
 
  1. $("#imgCutConfirm").bind("click",function(){  
  2. <span style="white-space:pre">    </span>$("#containerDiv").hide();  
  3.   <span style="white-space:pre"</span>$("#imgEdit").hide();  
  4. <span style="white-space:pre">    </span>$("#getCroppedCanvasModal").modal("hide");  
  5. })  



 

获取截图 并ajax提交,  

 

[html] view plain copy
 
  1. //提交表达  
  2.     function submitForm(){  
  3.         $("#registerForm").attr("enctype","multipart/form-data");  
  4.           
  5.         var formData = new FormData($("#registerForm")[0]);  
  6.         formData.append("imgBase64",encodeURIComponent(fileImg));//  
  7.         formData.append("fileFileName","photo.jpg");  
  8.           
  9.           
  10.         $.ajax({    
  11.             url: "",  
  12.             type: \'POST\',    
  13.             data: formData,    
  14.             timeout : 10000, //超时时间设置,单位毫秒  
  15.             async: true,    
  16.             cache: false,    
  17.             contentType: false,    
  18.             processData: false,   
  19.             success: function (result) {   
  20.             },    
  21.             error: function (returndata) {  
  22.             }  
  23.         });  
  24.     }  

 

使用canvas生成的截图。我只找到生成base64的。就是那一长串字符。。

原本我想生成jpg / png ,,没找到。  

后来找到在后台 把base64 的转成jpg/png  的方法。

然后又把图片上传到七牛上面,发现可以使用二进制流上传,就不用jpg了

  后台处理base64 java代码片段

 

[html] view plain copy
 
  1. /**  
  2.      * 上传base64   
  3.      * @param imgBase64 图片base64  
  4.      * @param fileName 图片名称  
  5.      * @return  
  6.      */  
  7.     private String uploadImgBase64(String imgBase64,String fileName){  
  8.           
  9.         String uploadPath=FILEDATE;  
  10.         String fileExt = fileFileName.substring(fileFileName.lastIndexOf(".") + 1).toLowerCase();//上传的文件的后缀  
  11.         String newFileName = fileName+ "." + fileExt;//上传后的文件名字  
  12.         String uploadPathName = uploadPath + newFileName;//获取到上传后的文件路径+文件名  
  13.           
  14.         BASE64Decoder decoder = new BASE64Decoder();  
  15.           
  16.         imgBase64 = imgBase64.substring(30);    
  17.           
  18.         try {  
  19.             imgBase64 = URLDecoder.decode(imgBase64,"UTF-8");  
  20.               
  21.             byte[] decodedBytes = decoder.decodeBuffer(imgBase64);// 将字符串格式的imagedata转为二进制流(biye[])的decodedBytes  
  22.             for(int i=0;i<decodedBytes.length;++i){    
  23.                 if(decodedBytes[i]<0) {  
  24.                     //调整异常数据    
  25.                     decodedBytes[i]+=256;    
  26.                 }    
  27.             }  
  28.               
  29.             //使用七牛上传  
  30.             new QiniuUploadFile().upload(decodedBytes, uploadPathName);  
  31.         } catch (IOException e) {  
  32.             e.printStackTrace();  
  33.         }   
  34.           
  35.         return uploadPathName;  
  36.           
  37.     }  

 

 

我参考的文章咻咻咻

 

1.jQuery简单且功能强大的图片剪裁插件          

2.英文copper  api 当找不到方法时,可以看这里,不要怕英文版的,实在不行你可以一个一个试过去看看效果哈哈。不会告诉你我就是这么干的。

 

 

3.HTML5 本地裁剪图片并上传至服务器(老梗)