功能需求:
实现本地图片裁剪功能,要求裁剪得到的图片像素在420-1500px之间,不大于2M,并将裁剪后图片传给后台
使用插件:
Cropper(项目地址:https://github.com/fengyuanchen/cropper)实现裁剪
Web Uploader(项目地址:https://github.com/fex-team/webuploader)实现图片上传
功能实现:
1.HTML
1 <div> 2 <div class="up-pick"> 3 <a href="javascript:void(0)" id="picker">上传图片</a> 4 </div> 5 <input type="file" class="fileInput" hidden /> 6 </div>
2.CSS
引入cropper.css文件
3.JS
由于cropper依赖于jQuery,这里引入jQuery,cropper.js和webuploader.js
1 // 触发input file 2 $("#picker").on('click', function () { 3 $(this).parents(".up-pick").siblings(".fileInput").trigger("click"); 4 });
编写input file change事件
1 $(".fileInput").on('change', function() { 2 var file = this.files[0]; //获取上传图片,IE有兼容性问题 3 4 //检测图片格式和大小的合理性,在这里为了简便,用console.log。实际项目中可用Dialog组件做弹窗提示 5 if(!(file.type == 'image/jpeg' || file.type == 'image/jpg' || file.type == 'image/gif' || file.type == 'image/png')) { 6 console.log('支持图片格式:GIF、JPG、JPEG、PNG'); 7 $(".fileInput").val(''); 8 return; 9 }else if(file.size > 2097152) { 10 console.log('图片大小不超过2M'), 11 $(".fileInput").val('');//这里若不清空,再次传入同一张图片,input file的change事件不会触发 12 return; 13 } 14 15 // 初始化WebUploader 16 var uploader = WebUploader.create({ 17 auto: true,// 选完文件后,是否自动上传。 18 server: '/Image/productImageUploader',// 文件接收服务端。 19 fileSingleSizeLimit: 2 * 1024 * 1024, 20 duplicate: true, 21 accept: {// 只允许选择图片文件。 22 title: 'Images', 23 extensions: 'jpg,jpeg,png', 24 mimeTypes: 'image/jpg,image/jpeg,image/png' 25 } 26 }); 27 28 var image; //上传的图片 29 var cropper; //cropper对象 30 var reader = new FileReader(); 31 32 reader.onload = function() { 33 var url = reader.result; 34 var cropperImg = new Image(); //这步操作是为了拿到图片的尺寸 35 cropperImg.src = url; 36 37 cropperImg.onload = function() { 38 if(this.width < 420 || this.height < 420){ 39 console.log('图片尺寸应大于420*420像素'); 40 $(".fileInput").val('') 41 return; 42 } 43 44 //所有检测通过,弹出弹窗,在弹窗中进行图片裁剪操作 45 new Dialog({ 46 title: "裁剪图片", 47 content: '<div class="modifyBg"><div class="imgWrapper"><img id="image" src="' + url + '"></div></div>', 48 button: [{ 49 value: '确定', 50 callback: function () { 51 var type = $(image).attr('src').split(';')[0].split(':')[1];//得出图片格式:类似image/jpeg 52 var canVas = cropper.getCroppedCanvas();//获取裁剪后得到的canvas数据 53 var file = convertBase64UrlToBlob(canVas.toDataURL('image/jpeg','0.0'));//将canvas转换为Blob格式 54 uploader.addFiles(file);//将裁剪后的图片添加进webuploader上传到后台 55 this.close(); 56 } 57 }, { 58 value: '取消', 59 callback: function () { 60 $(".fileInput").val('') 61 this.close(); 62 } 63 }] 64 }).show(); 65 66 // 图片上传 67 image = document.querySelector('#image'); 68 cropper = new Cropper(image, { 69 viewMode: 1, //裁剪框只能在图片范围内移动 70 dragMode: 'move', //图片可以拖动 71 aspectRatio: 1, //裁剪比例,NaN-自由选择区域 72 zoomable: false, //禁止缩放,在控制裁剪像素,允许缩放会有问题 73 ready: function() { 74 cropper.setData({//初始裁剪区域占图片比例 75 width: 420, 76 height: 420 77 }) 78 }, 79 cropmove: function() { 80 var data = cropper.getData() 81 if(data.width > 1500 || data.height > 1500) { 82 cropper.setData({ 83 width: 1500, 84 height: 1500 85 }) 86 } 87 if(data.width < 420 || data.height < 420) { 88 cropper.setData({ 89 width: 420, 90 height: 420 91 }) 92 } 93 } 94 }); 95 }; 96 } 97 reader.readAsDataURL(file);//File对象转换为dataURL 98 99 uploader.on('uploadSuccess', function(file, rs) { 100 // 图片上传回调函数 101 }); 102 103 uploader.on('startUpload', function(file, rs) { 104 console.log("文件正在上传中,请稍候"); 105 }); 106 }
1 function convertBase64UrlToBlob(urlData){ 2 var bytes=window.atob(urlData.split(',')[1]);//去掉url的头,并转换为byte 3 4 //处理异常,将ascii码小于0的转换为大于0 5 var ab = new ArrayBuffer(bytes.length); 6 var ia = new Uint8Array(ab); 7 for (var i = 0; i < bytes.length; i++) { 8 ia[i] = bytes.charCodeAt(i); 9 } 10 11 return new Blob( [ab] , {type : 'image/jpeg'}); 12 }
列几个这里踩到的坑:
①图片裁剪前限制2M,但出现裁剪后图片大于2M的情况:
发现canVas.toDataURL方法接收两个参数,不传的话默认转为image/png格式,图片质量为1.0。这样就导致了裁剪后得到的图片大大大于原始图片。
查文档看到
如果type
参数的值为image/jpeg或
image/webp
,则第二个参数的值如果在0.0和1.0之间的话,会被看作是图片质量参数,如果第二个参数的值不在0.0和1.0之间,则会使用默认的图片质量.
于是我这里修改为 canVas.toDataURL('image/jpeg','0.0')
②由于技术栈使用webuploader结合cropper实现裁剪上传,这里我用了input file,整个的逻辑就是
通过change事件对图片格式和大小做合理性检验 → 通过H5中FileReader获取图片base64格式url → 再结合new Image()拿到图片尺寸,对图片尺寸做检验 → 进入裁剪阶段通过cropper.ready方法初始化裁剪框为图片像素420的大小,裁剪过程cropmove方法实时控制裁剪框的最大最小尺寸 → cropper.getCroppedCanvas获取裁剪后得到的canvas数据 → canVas.toDataURL转为base64格式 → 自定义convertBase64UrlToBlob方法将base64转为blob图片格式 → webuploader.addFiles方法上传最终的图片
③其实整个图片裁剪上传的过程并不难,主要是两个插件以及H5的API的运用,再结合实际的项目需求理清逻辑,按照需求实现功能。
最后:
从实习到正式,进入前端开发工作将近两年了,最近在项目开发中遇到一些问题,其实是以前曾经遇到过的,但是却不能很清晰记起以前是如何解决的,导致还要再去重新搜索回顾,解决问题的效率大大变慢。
于是觉得总结和思考,这项区别人与人之间能力差距的一个重要因素,更应该去重视和锻炼。
希望自己不要懒惰。