如何在微信公众号开发中实现图片裁剪

纵饮孤独 提交于 2020-03-01 20:45:03

接触微信公众号开发已经有一段时间了,发现其实和网页开发差不多,但是因为浏览器的不同,自己也碰过一些坑,其中就有怎么实现图片裁剪功能。

一开始我是用PC端的思路去做的,首先在本地获取图片路径,然后在网页中显示,最后在本地裁剪,然后把裁剪好的图片转换成base64数据,上传到服务器。做完之后,我为

了测试,我是直接把图片路径写到img里面的,省略了选择图片这个步骤,最后在微信测试是通过的。但是我把选择图片的步骤加上之后,就出了问题。

我是用cropper框架(不支持jq的版本)实现的,因为这个框架支持移动端操作的,下面我就把这个过程中出现的问题写一下。

    <!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部分会报错

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.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,这些代码是从一个项目复制过来的

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!