接触微信公众号开发已经有一段时间了,发现其实和网页开发差很少,可是由于浏览器的不一样,本身也碰过一些坑,其中就有怎么实现图片裁剪功能。javascript
一开始我是用PC端的思路去作的,首先在本地获取图片路径,而后在网页中显示,最后在本地裁剪,而后把裁剪好的图片转换成base64数据,上传到服务器。作完以后,我为css
了测试,我是直接把图片路径写到img里面的,省略了选择图片这个步骤,最后在微信测试是经过的。可是我把选择图片的步骤加上以后,就出了问题。html
我是用cropper框架(不支持jq的版本)实现的,由于这个框架支持移动端操做的,下面我就把这个过程当中出现的问题写一下。java
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> <title></title> <link rel="stylesheet" href="css/cropper.css" /> <style> .img-content img { max-width: 100%; } </style> </head> <body> <div class="img-content"> <!--src是微信的图片ID,能够直接在img里面显示--> <img id="photo" src="wxLocalResource://488970461173136"> </div> <button id="confirm">肯定</button> </body> <script type="text/javascript" src="js/cropper.js"></script> <script> var photo = document.getElementById("photo"); var cropper = new Cropper(photo, { aspectRatio: 1, }); document.getElementById('confirm').addEventListener('click', function() { var canvas=cropper.getCanvasData(); var base64Data=canvas.toDataURL("image/jpeg",1); alert(base64Data); }); </script> </html>
上面那段代码在微信端运行的时候,js部分会报错git
1,在cropper初始化的时候会报错,报XMLHtmlRequest DOM 18的错误github
2,在获取图片数据 toDataURL的时候会报错,报undefined function的错误ajax
其实这两个问题我以为应该是微信浏览器的问题。因此我用了另一种方式实现。仍是使用cropper裁剪插件json
一、把选择到的图片ID上传到微信的服务器,获取serverId(微信服务器的图片ID)canvas
二、修改cropper的js,使得cropper在初始化的时候不报错api
三、在本地裁剪,可是不获取裁剪后的base64数据,获取裁剪的区域参数,把serverId和那些参数发送到本身的服务器
四、从微信服务器下载图片到本身的服务器,裁剪,压缩,保存到本身的服务器。
下面我把全部的步骤都写出来
首先要使用微信js-sdk获取图片的ID,图片ID就是图片的路径,这个ID能够直接在img标签显示。
1,初始化微信js-sdk
2,调用微信选择图片的js
3,从返回的数据中获取图片ID
为了方便,我就写js部分
//微信初始化 wx.config({ debug: false, appId: '${wx_app_id}', timestamp: ${wx_js_timestamp}, nonceStr: '${wx_js_noncestr}', signature: '${wx_js_mydata}', jsApiList: [ 'chooseImage', 'uploadImage', ] }); //微信初始化成功 wx.ready(function(){ document.getElementById("picture").addEventListener('click', function(){ wx.chooseImage({ count: 1, //一次性能够选择多少张图片,默认9 sizeType: ['original','compressed'],//图片的类型:原图,压缩图 sourceType: ['album','camera'], //图片来源:相册,拍照 success: function(localRes){ var localIdVal = localRes.localIds[0]; //本地第一张图片ID //获取到图片后,上传的服务器,获得服务器的ID wx.uploadImage({ localId: localIdVal, //本地图片ID isShowProgressTips: 1, //显示加载圈 success: function (serverRes) { var serverIdVal=serverRes.serverId; window.location.href="mine/photocrop?localId="+localIdVal+"&serverId="+serverIdVal, }, fail: function (res) { mui.alert(JSON.stringify(res)); } }); }, cancel: function () { // } }); }); }); //微信初始化失败 wx.error(function(res){ document.getElementById("picture").addEventListener('tap', function(){ mui.alert("微信初始化失败"); }); });
首先要初始化微信,调用wx.config的方法,若是初始化成功,那么wx.ready就会调用,若是失败,那么就调用wx.error方法
初始化成功以后,给按钮添加点击的方法,这样点击的时候,就会调用wx.chooseImage的方法,在浏览器就会弹出选择图片的弹窗,选择图片以后,能够获取本地的图片ID,而后上传图片到服务器,能够获取微信服务器的图片ID。
如今说一下本地图片ID和微信服务器图片ID的用途,本地图片ID要用于裁剪的,服务器的图片ID是用于下载的。
下面修改cropper框架,其实初始化报错实际上是由于cropper会去下载本地的图片,因此咱们那段代码删掉
打开cropper.js,找到854行,把这段代码删掉,添加一句__this.clone(),这一句必须的。
其实咱们还须要禁掉滑轮缩放和手指缩放的功能,由于若是不由掉,那么裁剪框的区域就不正确了,把下面的代码注释掉
滑轮缩放的代码
手指缩放的代码
好了,cropper已经修改完了,记得要引用修改后的cropper.js
下面裁剪图片了
<!DOCTYPE html> <html> <head> <title>裁剪</title> <link rel="stylesheet" href="sources/css/cropper.css" /> <style> .img-content img { max-width: 100%; } </style> </head> <body> <div> <div class="img-content"> <img id="photo" src="${localId}"> </div> <button id="confirm"> 肯定 </button> </div> <script src="sources/js/cropper.js"></script> <script type="text/javascript" charset="utf-8"> mui.ready(function() { var photo = document.getElementById("photo"); var cropper = new Cropper(photo, { aspectRatio: 1, }); var btnConfirm = document.getElementById("confirm"); btnConfirm.addEventListener("tap", function() { btnConfirm.innerText = "正在处理..."; btnConfirm.disabled = true; var canvasData = cropper.getCanvasData(); var cropBoxData = cropper.getCropBoxData(); //要根据图片的缩放计算实际的大小 var scale = canvasData.naturalWidth / canvasData.width; var topVal = (cropBoxData.top - canvasData.top) * scale; var leftVal = cropBoxData.left * scale; var widthVal = cropBoxData.width * scale; mui.ajax('mine/uploadPhoto', { data: { serverId: '${serverId}', top: topVal, left: leftVal, width: widthVal }, type: 'post', dataType: 'json', success: function(data) { mui.alert(data.msg, function() { if (!data.success) { btnConfirm.innerText = "肯定"; btnConfirm.disabled = false; } }); }, error: function(xhr, type, errorThrown) { mui.alert(type); btnConfirm.innerText = "肯定"; btnConfirm.disabled = false; } }); }); }); </script> </body> </html>
首先用本地的图片ID显示,而后裁剪,获取裁剪的参数,而后把微信服务器的图片ID也上传到本身的服务器,而后在本身的服务器处理
下面这段代码包括从微信服务器下载图片,裁剪,压缩,保存到服务器
public static final String downloadUserPhoto(String serverId, int left, int top, int width) { String path = "http://file.api.weixin.qq.com/cgi-bin/media/get?access_token=fasdfsaffasdfa&media_id=" + serverId; HttpURLConnection con = null; FileOutputStream fos = null; try { URL url = new URL(path); con = (HttpURLConnection) url.openConnection(); con.setConnectTimeout(5000); con.connect(); if (con.getResponseCode() == HttpURLConnection.HTTP_OK) { String type = con.getHeaderField("Content-Type"); //判断是否是图片类型 if (type != null && type.contains("image")) { String ext = type.substring(type.lastIndexOf("/") + 1); String filename = UUID.randomUUID().toString() + "." + ext; File file = new File("download/images/",filename); if (!file.getParentFile().exists()) { file.getParentFile().mkdirs(); } BufferedImage bufImg = ImageIO.read(con.getInputStream()); bufImg = bufImg.getSubimage(left, top, width, width); //压缩图片,若是图片的像素宽度超过160 if (width > 160) { float wr = 160 * 1f / bufImg.getWidth(); AffineTransformOp ato = new AffineTransformOp(AffineTransform.getScaleInstance(wr, wr), null); bufImg = ato.filter(bufImg, null); } fos = new FileOutputStream(file); ImageIO.write(bufImg, ext, fos); String filepath = pathdir + "/" + filename; return filepath; } } } catch (Exception e) { e.printStackTrace(); try { if (fos != null) { fos.close(); } if (con != null) { con.disconnect(); } } catch (Exception el) { el.printStackTrace(); } } return null; }
其实最大的区别就是把本地裁剪移到服务器裁剪。没有demo,这些代码是从一个项目复制过来的