接触微信公众号开发已经有一段时间了,发现其实和网页开发差不多,但是因为浏览器的不同,自己也碰过一些坑,其中就有怎么实现图片裁剪功能。
一开始我是用PC端的思路去做的,首先在本地获取图片路径,然后在网页中显示,最后在本地裁剪,然后把裁剪好的图片转换成base64数据,上传到服务器。做完之后,我为
了测试,我是直接把图片路径写到img里面的,省略了选择图片这个步骤,最后在微信测试是通过的。但是我把选择图片的步骤加上之后,就出了问题。
我是用cropper框架(不支持jq的版本)实现的,因为这个框架支持移动端操作的,下面我就把这个过程中出现的问题写一下。
上面那段代码在微信端运行的时候,js部分会报错
1,在cropper初始化的时候会报错,报XMLHtmlRequest DOM 18的错误
2,在获取图片数据 toDataURL的时候会报错,报undefined function的错误
其实这两个问题我觉得应该是微信浏览器的问题。所以我用了另外一种方式实现。还是使用cropper裁剪插件
1、把选择到的图片ID上传到微信的服务器,获取serverId(微信服务器的图片ID)
2、修改cropper的js,使得cropper在初始化的时候不报错
3、在本地裁剪,但是不获取裁剪后的base64数据,获取裁剪的区域参数,把serverId和那些参数发送到自己的服务器
4、从微信服务器下载图片到自己的服务器,裁剪,压缩,保存到自己的服务器。
下面我把所有的步骤都写出来
首先要使用微信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.chooseImage的方法,在浏览器就会弹出选择图片的弹窗,选择图片之后,可以获取本地的图片ID,然后上传图片到服务器,可以获取微信服务器的图片ID。
现在说一下本地图片ID和微信服务器图片ID的用途,本地图片ID要用于裁剪的,服务器的图片ID是用于下载的。
下面修改cropper框架,其实初始化报错其实是因为cropper会去下载本地的图片,所以我们那段代码删掉
打开cropper.js,找到854行,把这段代码删掉,添加一句__this.clone(),这一句必须的。
其实我们还需要禁掉滑轮缩放和手指缩放的功能,因为如果不禁掉,那么裁剪框的区域就不正确了,把下面的代码注释掉
滑轮缩放的代码
手指缩放的代码
好了,cropper已经修改完了,记得要引用修改后的cropper.js
下面裁剪图片了
裁剪
下面这段代码包括从微信服务器下载图片,裁剪,压缩,保存到服务器
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,这些代码是从一个项目复制过来的
如果有什么问题,请给我留言