基于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标签,进行预览
                        width: 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='上传成功!')

 

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

 

 

 

 

 

 

posted @ 2019-07-13 08:35  roadcode  阅读(602)  评论(0编辑  收藏  举报