这段时间做一个公众号项目的开发,其中有一个功能涉及到微信网页调启相机或者拍照 选择图片后进行裁剪 然后转换base64 上传服务器。
思路:
1. 在本页面点击拍照或相册 调启相机或者相册 选择图片后 将图片传到裁剪页面
2. 在裁剪页面显示选择的图片 使用Cropper插件进行裁剪
3. 点击裁剪按钮 将Cropper裁剪的内容 利用canvas 将裁剪的图转换base64
4. 在预览页面 展示裁剪后的图片(base64 可直接在img 的src中使用)
最开始呢 想着微信有现成的js-sdk 可以使用,配合前端的Cropper 插件 应该很容易就实现选择图片裁剪功能,然而。。我真是太单纯了!!! 其中涉及到的问题有好大一堆。。emmm 想哭,最关键的问题就是跨域,关于跨域大家可以了解一下这篇博客 JavaScript跨域总结与解决办法,写的很详细 ,原因 以及一些解决办法,这是我看过大概比较全面的一篇博客了。 下面罗列一下遇到的问题
1. 微信选择图片然后进行裁剪 使用Cropper 无法显示选择的图片,原因是使用了微信jssdk选择的图片 某种程度上属于跨域。。
2. 裁剪后的图片进行base64转换,然而按照百度的方法 补充添加多种跨域解决办法都无法成功的进行canvas. toDataURL("image/jpg", 1),因为canvas的toDataURL 即时能够在画布上正常的显示裁剪的图片 也会因为跨域而无法获取到图画数据(Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.),百度后的解释是 画布污染 ,而百度后很多的解决办法是补充img.crossOrigin="anonymous";然并卵,这种方式只适用于子域名可能会有效果,详细的原因可以看这篇博客 canvas生成图片toDataURL报错的原因和解决方法
今天来了继续百度,想着或许可以换一种思路,于是使用了原始的input type=file的选择图片,虽然这种方式效果并不好 但是好歹功能出来了,比起解决跨域问题显得更为便捷(关键是跨域问题太难解决了,没有找到好的解决方案,ε=(´ο`*)))唉),上代码:
1. 选择页面 点击拍照或相册 都可以选择图片
<div class="bg_head"> <div class="" > <a href="javascript:;" target="_blank" ><img src="images/ggmuban/paizhao.png" onclick="choose(this)"><span>拍照</span></a> </div> <div class="" > <a href="javascript:;" target="_blank"><img src="images/ggmuban/xiangce.png" onclick="choose(this)"><span>相册</span></a> </div> </div> <input id="inputImage" name="file" type="file" accept="image/*">2. 选择图片后跳转裁剪页面
function choose(obj){ $('#inputImage').click(); var $inputImage = $('#inputImage'); URL = window.URL || window.webkitURL; if (URL) { $inputImage.change(function () { var files = this.files, file; if (files && files.length) { file = files[0]; if(!/image\/\w+/.test(file.type)){ layer.msg("请确保文件为图像类型"); return false; } var render = new FileReader(); render.readAsDataURL(file); render.onload = function(e){ localStorage.setItem("localData",this.result); //存储选择的图片 base64 location.href="cropper.html"; //裁剪页面 } } }); } else { $inputImage.parent().remove(); } }3. 裁剪页面-将选择的图片展示在被裁剪区域, 初始化Cropper (就是做一下设置),然后点击某个按钮进行裁剪,下面是裁剪页面全部的代码
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta http-equiv="Access-Control-Allow-Origin" content="*"> <title>裁剪图片</title> <link rel="stylesheet" href="css/cropper.css" /> <script type="text/javascript" src="js/jquery-1.8.3.min.js" ></script> <script type="text/javascript" src="js/cropper.js" ></script> <script type="text/javascript" src="js/common.js" ></script> <style> .container{width: 100%;height: 100%;position: fixed;} .canvas{/*width: 100%;*/height:60%;} .fade{width: 100%;height:20%;background-color: #000;} .btn_box{width: 60%;height:auto;margin: 0 auto;bottom: 0px;text-align: center;/*border: 1px solid red; */padding-top: 10%;} .btn_box div{opacity: .5;color:#fff;width: 40%;font-size:34px;border: 1px solid #A09F9F;padding: 20px 10px;display: inline-block;text-align: center;padding: 10px 20px;} #cut{border-bottom-right-radius: 100px;border-top-right-radius: 100px;} </style> </head> <body class="container"> <!-- 展示选择的图片 --> <div class="canvas"> <img id="image" src="" /> </div> <!-- 按钮 --> <div class="fade"> <div class="btn_box"> <div class="btn" onclick="javascript:window.history.go(-1);" style="border-bottom-left-radius: 100px;border-top-left-radius: 100px;">取消</div> <div class="btn" id="cut" >确定</div> </div> </div> <!-- 预览裁剪的图片 --> <div style="height:20%;"> <canvas id="canvas" style="border: 1px solid saddlebrown;"></canvas> <img src="" id="test" /> </div> <script> var local = localStorage.getItem("localData"); var $image = $("#image"); //裁剪区域要显示的图片 $image.attr("src",local); $image.on("load", function() {// 等待图片加载成功后,才进行图片的裁剪功能 $image.cropper({ aspectRatio: 4 / 1, viewMode:1, highlight:false, rotatable:false, background:true, zoomOnTouch:false, guides: false, //裁剪框的虚线 autoCropArea: 1,//0-1之间的数值,定义自动剪裁区域的大小,默认0.8 dragCrop: false,//是否允许移除当前的剪裁框,并通过拖动来新建一个剪裁框区域 movable: true, //是否允许移动剪裁框 resizable: true, //是否允许改变裁剪框的大小 zoomable: false, //是否允许缩放图片大小 mouseWheelZoom: false, //是否允许通过鼠标滚轮来缩放图片 touchDragZoom: false, //是否允许通过触摸移动来缩放图片 rotatable: false, //是否允许旋转图片 strict: true, toggleDragModeOnDblclick:false }); }); //裁剪 按钮 $("#cut").on("click", function() { //方法一:通过cropper的getCroppedCanvas方法可以拿到一个画有剪裁图片的canvas。 //但是测试后发现这种方法会导致裁剪的图片方法,需要进行比例缩放 // var dataURL = $('#image').cropper("getCroppedCanvas");//拿到剪裁后的数据 // var data = dataURL.toDataURL("image/jpg", 1);//转成base64 // alert("回调:"+data); //方法二:通过cropper的getCanvasData和getCropBoxData方法获取到裁剪的一些数 据,再通过canvas的toDataURL转换裁剪的图片为base64 var src = $image.attr("src"); var canvasdata = $image.cropper("getCanvasData"); var cropBoxData = $image.cropper('getCropBoxData'); convertToData(src, canvasdata, cropBoxData, function(basechar) { // 回调后的函数处理 // alert("回调:"+basechar); // localStorage.setItem("basechar",basechar); // location.href="test2.html";//预览base64 }); }) //重新绘制裁剪的图片 转换为base64 function convertToData(url, canvasdata, cropdata, callback) { var cropw = cropdata.width; // 剪裁区域的宽度。 var croph = cropdata.height; // 剪裁区域的高度 var imgw = canvasdata.width; // canvas新的宽度 var imgh = canvasdata.height; // canvas新的高度 // alert(cropw+","+croph+","+imgw+","+imgh); var poleft = canvasdata.left - cropdata.left; // canvas定位图片的左边位置 var potop = canvasdata.top - cropdata.top; // canvas定位图片的上边位置 // alert(poleft+","+potop); // var canvas = document.createElement("canvas");//通过js创建canvas 但是页面看不到裁剪后的图片 需要自己拿到裁剪的base64后在显示出来 var canvas = document.getElementById("canvas");//如果是本页面展示 可以在页面创建一个canvas 可以看到裁剪工具裁剪的图片 var ctx = canvas.getContext('2d'); canvas.width = cropw; canvas.height = croph; var img = new Image(); img.src = url; img.onload = function() { this.width = imgw; this.height = imgh; ctx.drawImage(this, poleft, potop, this.width,this.height); var base64 = canvas.toDataURL("image/jpg", 1); // 这里的“1”是指的是处理图片的清晰度(0-1)之间,当然越小图片越模糊,处理后的图片大小也就越小 callback && callback(base64) // 回调base64字符串 } img.onerror = function () { alert("error") } } </script> </body> </html>
最后 附上Cropper的一下参数说明 简单功能强大的jQuery图片剪裁插件Image Cropper
以及相关参考博客:H5移动端图片裁剪(base64)、java -- cropper裁剪图片并base64上传 移动端简单示例