zoukankan      html  css  js  c++  java
  • mui开发app之cropper裁剪后上传头像的实现

    应广大读者建议,已经将该项目源码提交到地址: 
    https://github.com/devilyouwei/dashen

    在大多数app项目中,都需要对用户头像的上传,之前做web开发的时候,我主要是通过input type=file的标签实现的,上传后,使用php对图片进行裁剪,这种方式比较传统简单。

    此次app开发中需要做到用户选择本地相册或者进行拍照->对照片进行裁剪->最后同时更新本地头像和服务器端的图片。(app常见套路)

    我将要结合:mui,cropper,jquery开发!

    实现思路:

    1.用户点击头像,打开actionsheet

    2.选择图片或者拍照后返回的图片绝对地址传入单独的裁剪页面,跳转到裁剪页面

    3.裁剪页面裁剪后选择确认则将裁减后图片保存到localstorage中(其实是把整个图片保存到本地数据库中)

    4.触发一个更新上一页头像的事件,返回上一页

    5.看到图片已经更改

    6.保存,图片上传到服务器(json)

    7.服务器将图片的base64保存到数据库(text类型),实现数据库保存图片,当然可以使用后端语言的方法还原为图片后保存在文件系统中(建议:小图可保存在数据库中,大图保存在文件系统)

    实现工具和插件,直接看代码:

    js

    <script type="text/javascript" src="../js/jquery-1.11.2.min.js"></script>
    <script src="../js/mui.min.js"></script>
    <script type="text/javascript" src="../js/exif.js"></script>
    <script src="../js/cropper.min.js"></script>
    <script src="../js/fastclick.js"></script>

    css

    <link href="../css/mui.min.css" rel="stylesheet" />
    <link href="../css/iconfont.css" rel="stylesheet" />
    <link href="../css/cropper.css" rel="stylesheet" />

    这里我们主要使用了一个cropper.js的插件,自行百度下载,目前比较好用的插件只有这个,大神的话自己写一个吧

    注意cropper必须使用jquery,而jquery比较臃肿,在其他mui中尽量不要引入,我也是迫不得已,使用jq并非我本意

    fastclcik.js是加速点击触发,一般在手机端开发其实用不到,因为一般使用tap,这里我加了进去,似乎对裁剪图片时手势操作有帮助,(+_+)?,不加也没有影响,测试过

    iconfont是按钮图标

    exif.js是可以检测图片拍摄时采用横向还是纵向

    这几个请自行百度下载!

    接下来可以开发了:

    一共两个页面,

    headinfo.html——编辑页面

    cropper.html——裁剪页面

    headinfo.html

    <!doctype html>
    <html>
    
        <head>
            <meta charset="UTF-8">
            <title>我的资料</title>
            <meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1,user-scalable=no">
            <link href="../css/mui.min.css" rel="stylesheet" />
            <link href="../css/style.css" rel="stylesheet" />
            <style type="text/css">
                .head {
                    height: 40px;
                }
                
                #head {
                    line-height: 40px;
                }
                
                .head-img {
                    width: 40px;
                    height: 40px;
                }
                
                #head-img1 {
                    position: absolute;
                    bottom: 10px;
                    right: 40px;
                    width: 40px;
                    height: 40px;
                }
                
                .mui-fullscreen {
                    position: fixed;
                    z-index: 20;
                    background-color: #000;
                }
                
                .mui-content {
                    position: absolute;
                    left: 0;
                    right: 0;
                    top: 0;
                    bottom: 0;
                }
            </style>
        </head>
    
        <body>
            <header class="mui-bar mui-bar-nav">
                <button type="button" id="finish" class="mui-left mui-btn mui-btn-link mui-btn-nav mui-pull-left">
                        <span class="mui-icon mui-icon-left-nav"></span>完成
                </button>
                <h1 class="mui-title">头信息</h1>
            </header>
            <div class="mui-content">
    
                <ul class="mui-table-view">
                    <li class="mui-table-view-cell">
                        <a id="head" class="mui-navigate-right">个人头像
                            <span class="mui-pull-right head">
                                <img class="head-img mui-action-preview" id="head-img1" src=""/>
                            </span>
                        </a>
                    </li>
                </ul>
    
                <div class="mui-input-row mui-margin-vertical">
                    <h5 class="mui-margin-horizontal-xs">个人签名:</h5>
                    <input class="mui-padding-lg" id="signature" type="text" placeholder="个人签名" />
                </div>
            </div>
    
            <script src="../js/mui.min.js"></script>
            <script src="../js/app.js"></script>
            <script type="text/javascript">
                (function($) {
                    mui.init({
                        swipeBack: true
                    });
    
                    $.plusReady(function() {
                        //初始化头像,和预览图
                        setTimeout(function() {
                            defaultInfo();
                            setTimeout(function() {
                                initImgPreview();
                            }, 200);
                        }, 0);
    
                        //弹出菜单
                        mui(".mui-table-view-cell").on("tap", "#head", function(e) {
                            if(mui.os.plus) {
                                var a = [{
                                    title: "拍照"
                                }, {
                                    title: "从手机相册选择"
                                }];
                                plus.nativeUI.actionSheet({
                                    title: "修改头像",
                                    cancel: "取消",
                                    buttons: a
                                }, function(b) {
                                    switch(b.index) {
                                        case 0:
                                            break;
                                        case 1:
                                            getImage();
                                            break;
                                        case 2:
                                            galleryImg();
                                            break;
                                        default:
                                            break
                                    }
                                })
                            }
    
                        });
    
                        //完成并返回
                        document.getElementById("finish").addEventListener("tap", function() {
                            var newSign = document.getElementById("signature").value;
                            var oldSign = app.getUserInfo().signature;
                            if(oldSign === newSign)
                                $.back();
                            else {
                                app.request("User", "updateSignature", {
                                    'signature': newSign
                                }, function(res) {
                                    if(res.login == 0) {
                                        mui.toast(res.info);
                                        app.clearToken();
                                        app.toLogin();
                                        return false;
                                    }
                                    if(res.status == 1) {
                                        app.setSignature(newSign);
                                        mui.toast(res.info);
                                        var view = plus.webview.getWebviewById("index");
                                        $.fire(view, "updateHeadInfo");
                                        $.back();
                                    } else {
                                        mui.toast(res.info);
                                    }
                                });
                            }
    
                        });
    
                    });
    
                    //拍照
                    function getImage() {
                        var c = plus.camera.getCamera();
                        c.captureImage(function(e) {
                            //存储到本地
                            plus.io.resolveLocalFileSystemURL(e, function(entry) {
                                cutImage(entry.toLocalURL());
                            }, function(e) {
                                console.log("读取拍照文件错误:" + e.message);
                            });
                        }, function(s) {
                            console.log("error" + s);
                        }, {
                            filename: "_doc/head.jpg"
                        })
                    }
    
                    //相册
                    function galleryImg() {
                        plus.gallery.pick(function(a) {
                            plus.io.resolveLocalFileSystemURL(a, function(entry) { //entry为图片原目录(相册)的句柄
                                cutImage(entry.toLocalURL());
                            }, function(e) {
                                console.log("读取图片错误:" + e.message);
                            });
                        }, function(a) {}, {
                            filter: "image"
                        })
                    };
    
                    //设置默认头像
                    function defaultInfo() {
                        var my_icon = app.getHeadImg(); //头像
                        var signature = app.getUserInfo().signature; //签名
                        if(my_icon && my_icon != "") {
                            document.getElementById("head-img1").src = my_icon;
                        } else {
                            document.getElementById("head-img1").src = '../images/my_icon.jpg';
                        }
                        if(signature && signature != "") {
                            document.getElementById("signature").value = signature;
                        } else {
                            document.getElementById("signature").value = "";
                        }
                    }
    
                    //预览图像
                    document.getElementById("head-img1").addEventListener('tap', function(e) {
                        e.stopPropagation(); //阻止冒泡
                    });
    
                    function initImgPreview() {
                        var imgs = document.querySelectorAll("img.mui-action-preview");
                        imgs = mui.slice.call(imgs);
                        if(imgs && imgs.length > 0) {
                            var slider = document.createElement("div");
                            slider.setAttribute("id", "__mui-imageview__");
                            slider.classList.add("mui-slider");
                            slider.classList.add("mui-fullscreen");
                            slider.style.display = "none";
                            slider.addEventListener("tap", function() {
                                slider.style.display = "none";
                            });
                            slider.addEventListener("touchmove", function(event) {
                                event.preventDefault();
                            })
                            var slider_group = document.createElement("div");
                            slider_group.setAttribute("id", "__mui-imageview__group");
                            slider_group.classList.add("mui-slider-group");
                            imgs.forEach(function(value, index, array) {
                                //给图片添加点击事件,触发预览显示;
                                value.addEventListener('tap', function() {
                                    slider.style.display = "block";
                                    _slider.refresh();
                                    _slider.gotoItem(index, 0);
                                })
                                var item = document.createElement("div");
                                item.classList.add("mui-slider-item");
                                var a = document.createElement("a");
                                var img = document.createElement("img");
                                img.setAttribute("src", value.src);
                                a.appendChild(img)
                                item.appendChild(a);
                                slider_group.appendChild(item);
                            });
                            slider.appendChild(slider_group);
                            document.body.appendChild(slider);
                            var _slider = mui(slider).slider();
                        }
                    }
    
                    //裁剪图片
                    function cutImage(path) {
                        $.openWindow({
                            url: 'cropper.html',
                            id: 'cropper',
                            extras: {
                                path: path,
                            },
                            show: {
                                aniShow: 'zoom-fade-in',
                                duration: 800
                            },
                            waiting: {
                                autoShow: true
                            }
                        });
                    }
    
                    //更新用户头像
                    function update_head_img(e) {
                        var my_icon = e.detail.img;
                        //先上传
                        app.request("User", "saveHeadImg", {
                            'my_icon': my_icon
                        }, function(res) {
                            if(res.login == 0) {
                                mui.toast(res.info);
                                app.clearToken();
                                app.toLogin();
                                return false;
                            }
    
                            if(res.status == 1) {
                                app.setHeadImg(my_icon); //确认上传成功后存储到本地
                                if(my_icon == "")
                                    my_icon = "../images/my_icon.jpg";
                                document.getElementById("head-img1").src = my_icon; //刷新小图
                                document.querySelector("#__mui-imageview__group .mui-slider-item img").src = my_icon; //刷新预览图
                                //顺带触发上一个页面的updateHeadInfo
                                var view = plus.webview.getWebviewById("index");
                                $.fire(view, "updateHeadInfo");
                                mui.toast(res.info);
                            } else {
                                mui.toast(res.info);
                            }
    
                        });
    
                    }
                    window.addEventListener("updateHeadImg", update_head_img); //添加自定义事件,其他页面调用
                })(mui);
            </script>
        </body>
    
    </html>
    View Code

    cropper.html

    <!DOCTYPE html>
    <html>
    
        <head>
            <meta charset="utf-8">
            <title>裁剪头像</title>
            <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
            <link href="../css/mui.min.css" rel="stylesheet" />
            <link href="../css/cropper.css" rel="stylesheet" />
            <style type="text/css">
                body {
                    background-color: #000000;
                }
                
                #cropper-example-1 {
                    background-color: #000000;
                    height: 93%;
                    width: 100%;
                    position: absolute;
                }
                
                .divbut {
                    width: 100%;
                    text-align: center;
                    position: fixed;
                    z-index: 2;
                    bottom: 0px;
                    background-color: #000000;
                    height: 7.5%;
                    line-height: 50px;
                }
                
                .divbut>div:first-child {
                    float: left;
                    width: 20%;
                }
                
                .divbut>div:last-child {
                    float: right;
                    width: 20%;
                }
                
                img#im {
                    height: 100%;
                    width: 100%;
                }
            </style>
        </head>
    
        <body>
            <div id="cropper-example-1" class="mui-hidden">
                <img id="im" alt="Picture" />
            </div>
    
            <div class="divbut">
                <div>
                    <p id="quxiao" class="mui-icon mui-icon-closeempty"></p>
                </div>
                <div>
                    <p id="xuanqu" class="mui-icon mui-icon-checkmarkempty"></p>
                </div>
            </div>
            <img src="" alt="" class="mui-hidden" id="im_exif" />
    
            <script type="text/javascript" src="../js/jquery-1.11.2.min.js"></script>
            <script src="../js/mui.min.js"></script>
            <script type="text/javascript" src="../js/exif.js"></script>
            <script src="../js/cropper.min.js"></script>
            <script src="../js/fastclick.js"></script>
            <script src="../js/app.js"></script>
    
            <script>
                $(function() {
                    //尽量用一下fastclick
                    FastClick.attach(document.body);
                    ! function() {
                        var i = {
                            aspectRatio: 1 / 1
                        };
                    }()
                });
    
                (function(c) {
                    var Cro = function() {}
                    c.extend(Cro.prototype, {
                        orientation: null,
                        urldata: null,
                        view: null,
                        num: 0,
                        sbx: null,
                        sby: null,
                        n: 0,
                        onReady: function() {
                            var that = this;
                            mui.init();
                            that.bindEvent();
                            that.view = plus.webview.currentWebview();
    
                            var img = document.getElementById("im_exif");
                            img.src = that.view.path;
                            img.addEventListener("load", function() {
                                //exif调整图片的横竖
                                EXIF.getData(this, function() {
                                    var orientation = EXIF.getAllTags(this).Orientation;
                                    $("#im").attr("src", that.loadcopyImg(img, orientation));
                                    document.getElementById("cropper-example-1").classList.remove("mui-hidden"); //显示裁剪区域
                                    that.cropperImg();
                                });
                            })
                        },
                        cropperImg: function() {
                            var that = this;
                            $('#cropper-example-1 > img').cropper({
                                aspectRatio: 1 / 1,
                                autoCropArea: 1,
                                strict: true,
                                background: false,
                                guides: false,
                                highlight: false,
                                dragCrop: false,
                                movable: false,
                                resizable: false,
                                crop: function(data) {
                                    that.urldata = that.base64(data);
                                }
                            });
                        },
                        loadcopyImg: function(img, opt) {
                            var that = this;
                            var canvas = document.createElement("canvas");
                            var square = 500;
                            var imageWidth, imageHeight;
                            if(img.width > img.height) {
                                imageHeight = square;
                                imageWidth = Math.round(square * img.width / img.height);
                            } else {
                                imageHeight = square; //this.width;
                                imageWidth = Math.round(square * img.width / img.height);
                            }
                            canvas.height = imageHeight;
                            canvas.width = imageWidth;
                            if(opt == 6) {
                                that.num = 90;
                            } else if(opt == 3) {
                                that.num = 180;
                            } else if(opt == 8) {
                                that.num = 270;
                            }
                            if(that.num == 360) {
                                that.num = 0;
                            }
    
                            var ctx = canvas.getContext("2d");
                            ctx.translate(imageWidth / 2, imageHeight / 2);
                            ctx.rotate(that.num * Math.PI / 180);
                            ctx.translate(-imageWidth / 2, -imageHeight / 2);
                            ctx.drawImage(img, 0, 0, imageWidth, imageHeight);
                            var dataURL = canvas.toDataURL("image/jpeg", 1);
                            return dataURL;
                        },
                        bindEvent: function() {
                            var that = this;
                            document.getElementById("quxiao").addEventListener("tap", function() {
                                mui.back(); //取消就直接返回
                            });
                            document.getElementById("xuanqu").addEventListener("tap", function() {
                                //触发上一个页面刷新图片事件
                                var preView = plus.webview.getWebviewById('user/headinfo');
                                mui.fire(preView, 'updateHeadImg', {
                                    'img': that.urldata
                                }); //不能保存图片,需要判断上传性,所以选择传值的方式,传递图片,格式为json
                                mui.back();
                            });
                        },
                        base64: function(data) {
                            var that = this;
                            var img = document.getElementById("im");
    
                            var canvas = document.createElement("canvas");
                            //像素
                            canvas.height = 400;
                            canvas.width = 400;
                            var bx = data.x;
                            var by = data.y;
                            var ctx = canvas.getContext("2d");
                            ctx.drawImage(img, bx, by, data.width, data.height, 0, 0, 400, 400);
                            var dataURL = canvas.toDataURL("image/jpeg", 0.5); //第二个参数是质量
                            return dataURL;
                        }
                    });
    
                    var cro = new Cro();
    
                    c.plusReady(function() {
                        cro.onReady();
                    })
                })(mui)
            </script>
        </body>
    
    </html>
    View Code

    一开始对于headinfo.html我是打算先将拍照和相册获取的图片使用plus的io保存到项目app的_doc目录下再编辑裁剪,但是发现可以精简,直接把图片的绝对地址传到cropper中,直接编辑后保存为base64,放在localstorage中,以后需要头像的地方直接从localstorage中获取即可!我在app.js(这是我写的项目的公共js类库,处处引用)

    /* 
     *这只是其中一部分,在裁剪过程中需要用到的库函数 
     *主要是方便,随时可以获取保存在localstorage中的头像base64图
    */
    
    (function($, owner) {
        
         // 获取用户个人信息
        owner.getUserInfo = function() {
            var userText = localStorage.getItem('$user') || "{}";
            return JSON.parse(userText);
        }
    
         // 存储用户个人信息
        owner.setUserInfo = function(user) {
            user = user || {};
            localStorage.setItem('$user', JSON.stringify(user));
        }
    
        // 获取用户头像
        owner.getHeadImg = function() {
            var headImg = owner.getUserInfo().my_icon || "";
            return headImg;
        }
    
        //设置用户头像
        owner.setHeadImg = function(baseData) {
            var userInfo = owner.getUserInfo();
            userInfo.my_icon = baseData; //只对my_icon这一项进行修改,其他不动
            owner.setUserInfo(userInfo);
        }
        
    
    }(mui, window.app = {}));

    base64的图片格式是html5 canvas所使用的图片格式,可以直接放入img的src中!

    注:如果想使用js直接在手机端将base64转换为图片文件请看:mui开发app之js将base64转图片文件

    效果图:

                   

  • 相关阅读:
    把A库aa表结构复制到B库中生成bb表
    C #登录代码
    C# 跟查询有关的代码
    C# 输出用“*”组成的菱形
    POJ 3696 The Luckiest number 数论,GCD
    用一句SQL取出第 m 条到第 n 条记录的方法
    Web Services的基本原理
    常用SQL语句
    什么应用适合Web Services
    应该了解的垃圾收集机制(一)
  • 原文地址:https://www.cnblogs.com/devilyouwei/p/6322737.html
Copyright © 2011-2022 走看看