zoukankan      html  css  js  c++  java
  • 基于cropper和sweetalert的简单图片/头像裁剪上传

    基本功能

    前端基本样式:

    进行图片裁剪及上传:

    点击上传后,js会将截取到的数据转为图片数据利用ajax发送给后台进行存储。存储成功后,刷新前端页面,头像改变。

    上传成功后:自动刷新网页,更改头像

     基本工具

    cropper是一个功能强大的jq插件,在指定图片img上添加裁剪框,并根据指定事件对图片按照裁剪框的大小进行裁剪。

    crepper还可以对定义图片翻转、放大、移动以及输出裁剪框位置的很多功能,由于此处只是用于头像上传,所以只使用了基本功能。

    cropper使用时需要用到jq2.0以上,所以加载cropper之前,一定要先加载jq,不然会报错。

    sweetalert是一个界面优美使用简单、完全基于jq的一个模态框插件。由于自己在练习中使用sweetalert作为弹出框窗口,所以此处就没有自己写模态框也没有利用bootstrap的模态框。

    后端是使用django进行处理。

    基本代码

    html:为了方便,使用了bootstrap样式。

    加载库:

     <link rel="stylesheet" href="dist/css/bootstrap.min.css">
     <script src="dist/jquery.min.js"></script>
     <script src="js/sweetalert.min.js"></script>
     <script src="js/cropper.min.js"></script>
     <link rel="stylesheet" href="css/cropper.min.css">
        <div class="row">
            <div class=" col-sm-offset-1 col-sm-2 outter">
                {% csrf_token %}
                <div class="thumbnail ">
                    <img id="img_thumbnail" src="/media/{{ user.thumbnail }}" alt="头像">
                    <div class="btn-wrapper">
                    <label class="btn btn-info btn-block btn-sm" id="up-btn">上传头像
                        <input id="up_thumbnail" type="file" style="display: none">
                    </label>
                </div>
                </div>
            </div>
        </div>

     上传头像的input标签是隐藏在label中的。

    css样式:

    .row{
      .outter{
        .thumbnail{
          padding: 0;
          border: none;
          background-color: inherit;
          #img_thumbnail{
            width: 100%;
            object-fit: cover;
          }
          .btn-wrapper{
            margin-top: 5px;
          }
        }
      }
    }

    用的是sass语法,可以转换为css。

    这里对图片显示用到了object-fit属性。因为前台显示图片的头像框大小是固定的,有时候上传的头像太小,这个属性可以将该图片填充满头像框。

    js代码:

    //将base64转换为文件,截取图片后会用到
    function dataURLtoFile(dataurl, filename) {
        var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
            bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
        while (n--) {
            u8arr[n] = bstr.charCodeAt(n);
        }
        return new File([u8arr], filename, {type: mime});
    }
    
    $(function () {
        var up_thumbnail = $('#up_thumbnail');  //获取上传文件的input对象
    
        //选中文件后,触发change事件:
        up_thumbnail.change(function () {
            var file = this.files[0];  //获取图片对象
    
            //读取文件对象,弹出模态框,对图片进行预览
            filereader = new FileReader();
            filereader.readAsDataURL(file);
            filereader.onload = function () {
                //弹出模态框,模态框的内容content是一个img标签,classname是source-img,这个标签cropper要用到
                swal({
                    content: {
                        element: 'img',
                        attributes: {
                            src: this.result,//此处的this.result就是读取的文件数据,放至img标签,进行预览
                             400,
                            className: 'source-img'
                        }
                    },
                    buttons: {
                        cancel: { //取消按钮,点击后为null
                            text: '取消',
                            closeModal: true,
                            visible: true,
                        },
                        confirm: {   //确认按钮,点击后会返回true
                            text: '上传',
                            closeModal: false,
                            className: 'cut-btn',
                        }
                    },
                }).then((value) => {  //点击按钮后,会将按钮的值传递给value,根据value进行下一步动作
                    if (value) {  //如果value为真
                        if ($(".source-img").attr("src") == null) {  //图像框中没有图像,弹出error模态框,1秒后自动关闭
                            swal({
                                icon: 'error',
                                title: '没有图片上传',
                                timer: 1000
                            });
                        } else {  //图像框中有图像
                            var cas = $('.source-img').cropper('getCroppedCanvas');// 获取被裁剪后的canvas
                            var base64 = cas.toDataURL('image/jpeg'); // 转换为base64
                            var picture = dataURLtoFile(base64, file.name);//转换为图片对象
    
                            //使用ajax对图片文件进行传递
                            // 注意:这里的xfz_ajax是我自己写的对一个小封装,实际上就是自动将csrf_token的值加载到header,直接使用jq的ajax也可以实现。只不过多个步骤而已。
                            var formdata = new FormData();
                            formdata.append('thumbnail', picture); //前面为主键名,后面为文件对象
                            //使用jq的ajax时,post请求一定要记着带上csrf_token的值。
                            xfz_ajax.post({
                                'url': '/cms/upto_thumbnail/',
                                'data': formdata,
                                'processData': false,  //使用当前的数据,不用序列化
                                'contentType': false,//
                                'success': function (result) {
                                    if (result.code === 200) {  //这个后台返回的code信息是我自定义的,上传成功会返回一个resul字典,其中一个key为code,成功值为200
                                        swal({   //上传成功,显示success模态框。其显示的信息为返回的信息。1.5秒后自动关闭模态框,并自动刷新网页
                                            title: result.message,
                                            icon: 'success',
                                            timer: 1500
                                        }).then(() => {
                                            window.location.reload()
                                        })
                                    } else {
                                        swal({  //上传失败,弹出失败模态框
                                            title: result.message,
                                            icon: 'error',
                                            timer: 1500
                                        })
                                    }
                                }
                            })
    
                        }
    
                    }
                });
    
                //在生成模态框之后(只有生成了模态框,才有cropper需要的img标签)时候对cropper进行初始化。
                $('.source-img').cropper({
                    aspectRatio: 1,// 默认比例
                    preview: '#previewImg',// 预览视图,可以不要,如果想要预览,可以将一个img标签的id放进来
                    guides: true, // 裁剪框的虚线(九宫格)
                    autoCropArea: 0.8, // 0-1之间的数值,定义自动剪裁区域的大小,默认0.8
                    movable: false, // 是否允许移动图片
                    dragCrop: true, // 是否允许移除当前的剪裁框,并通过拖动来新建一个剪裁框区域
                    movable: true, // 是否允许移动剪裁框
                    resizable: true, // 是否允许改变裁剪框的
                    zoomable: false, // 是否允许缩放图片大小
                    mouseWheelZoom: false, // 是否允许通过鼠标滚轮来缩放图片
                    touchDragZoom: true, // 是否允许通过触摸移动来缩放图片
                    rotatable: false, // 是否允许旋转图片
                    crop: function (e) {
                    }
                });
            };
        });
    });

     注意,ajax传递数据由于是用的一个ajax的小封装,省略了csrf_token的过程,使用时传递数据一定要携带csrf_token值。

     

     

    以上前端代码就已经全部完成了,后端代码我使用的是django,直接利用model获取文件。

    @require_POST
    @login_required(login_url='news:news_index')
    def upto_thumbnail(request):
        file = request.FILES.get('thumbnail')
        request.user.thumbnail = file
        request.user.save()
        return result.success(message='上传成功!')

    一个简单实用的头像裁剪上传功能就实现了。

     

     

     

     

     

  • 相关阅读:
    tomcat源码springboot搭建的跑包含websocket的项目
    tomcat源码ant编译
    职责链设计模式最简单的实例
    完美解决asp.net core 3.1 两个AuthenticationScheme(cookie,jwt)共存在一个项目中
    基于领域驱动设计(DDD)超轻量级快速开发架构(二)动态linq查询的实现方式
    Html5 在手机端 input 默认弹出英文键盘
    Html Table 表格 画斜线
    多个单列索引和联合索引的区别
    springboot常用功能
    前端代码评审(Code Review)
  • 原文地址:https://www.cnblogs.com/ohahastudy/p/11179354.html
Copyright © 2011-2022 走看看