Django + clipper to preview, cut and upload the Avatar

Keywords: JSON Javascript github JQuery

Train of thought:

Using the front-end plug-in of clipper, the pictures are cropped. The screenshot generated by clipper is a series of base64 codes, and then it is converted to blob format, which is transmitted to the back-end for storage. In short, it means that the front-end cut pictures are sent to the back-end, rather than the cut data values are sent to the back-end for cutting

Clipper api:

https://github.com/fengyuanchen/cropper

Simple use of clipper:

html

<div>
  <img id="image" src="picture.jpg">
</div>

css

img {
  max-width: 100%; /*Must fill*/
}

js

var $image = $('#image');

$image.cropper({
  aspectRatio: 16 / 9,
  crop: function(event) {
    console.log(event.detail.x);
    console.log(event.detail.y);
    console.log(event.detail.width);
    console.log(event.detail.height);
    console.log(event.detail.rotate);
    console.log(event.detail.scaleX);
    console.log(event.detail.scaleY);
  }
});

//instantiation
var cropper = $image.data('cropper');

Using clipper to cut pictures

Import:
  <script src="{{STATIC_URL}}js/jquery.js"></script>
  <link  rel="stylesheet" type="text/css" href="{{STATIC_URL}}css/cropper.css" />
    <script src="{{STATIC_URL}}js/cropper.js" type="text/javascript" ></script>
css:
  body {
            font-size: 16px;
            font-family:"Microsoft YaHei",Arial, Helvetica, sans-serif
        }
        *,
        *:before,
        *:after {
            -webkit-box-sizing: border-box;
               -moz-box-sizing: border-box;
                -ms-box-sizing: border-box;
                    box-sizing: border-box;
        }

        .crop-picker-wrap {
            position: relative;
            width: 100px;
            height: 30px;
            overflow: hidden;
        }
        .crop-picker {
            width: 100%;
            height: 100%;
            line-height: 1;

            -webkit-appearance: none;
            margin: 0;
            border: none;
            border-radius: 5px;
            padding: 9px 0;
            background-color: #1ab2ff;

            color: #fff;            
            cursor: pointer;
        }
        .crop-picker-file {
            position: absolute;
            top: 0;
            right: 0;
            height: 100%;
            opacity: 0;
            cursor: pointer;
            filter: alpha(opacity=0);
        }

        .crop-save,
        .crop-cancel {
            display: inline-block;
            vertical-align: middle;

            width: 150px;
            height: 50px;
            line-height: 50px;

            -webkit-appearance: none;
            margin: 0 5px;
            border: none;
            border-radius: 5px;
            background-color: #1ab2ff;

            color: #fff;
            cursor: pointer;
        }

/* Apply these styles only when #preview-pane has
   been placed within the Jcrop widget */
.jcrop-holder #preview-pane {
  display: block;
  position: absolute;
  z-index: 2000;
  top: 10px;
  right: -280px;
  padding: 6px;
  border: 1px rgba(0,0,0,.4) solid;
  background-color: white;

  -webkit-border-radius: 6px;
  -moz-border-radius: 6px;
  border-radius: 6px;

  -webkit-box-shadow: 1px 1px 5px 2px rgba(0, 0, 0, 0.2);
  -moz-box-shadow: 1px 1px 5px 2px rgba(0, 0, 0, 0.2);
  box-shadow: 1px 1px 5px 2px rgba(0, 0, 0, 0.2);
}

/* The Javascript code will set the aspect ratio of the crop
   area based on the size of the thumbnail preview,
   specified here */
#preview-pane {
 float:right;
 }

#preview-pane .preview-container {
  overflow: hidden;
  border-style: groove;
  background-color: black;
  width: 160px;
  height: 160px;
}

#target {
    max-width: 100%; /* This rule is very important, please do not ignore this! */
}

.cut-container{
        width: 300px;
        height: 300px;
        margin:20px 30px;
        border:dashed #cacaca 1px;
}

#preview{
   max-width: 300px;
   max-height:300px;
}

#cropper-line{
      border-color:black;
}
   <div class="crop-picker-wrap">
      <button class="crop-picker" id='select' type="button">Select pictures</button>
     <input type="file" class="crop-picker-file" id="inputImage" name="file" accept=".jpg,.jpeg,.png,.gif,.bmp,.tiff">>
        </div>
    //preview
  <div id="preview">
             {% if thumb_pic %}
             <img src="{{MEDIA_URL}}{{thumb_pic}}" id="target" />   
             {% else%}
             <img src="" id="target" /> 
             {% endif %}    
               <span>Scroll to zoom in or out</span> 
          </div>
            // Show cropped renderings
          <div id="preview-pane">
            <div class="preview-container">
                 <img src="" id="cut_thumb"/>
            </div>
            <span>160*160</span>
          </div>

           <div class="crop-operate">
                <button class="crop-save" type='submit' id='save'>Preservation</button>
                <button class="crop-cancel" type="button" id='cancel'>cancel</button>
            </div>

The effect is as follows:

Use the scroll wheel to zoom in and out the picture. The width and height are 360 * 360

js:
var $image = $('#target');  
        $('[type=file]').change(function(e) {      
            var file = e.target.files[0]
            if(file.size>= 2*1024*1024){
                  layer.alert('Your uploaded picture is more than 2 M,Please upload again', {
                      title:'Tips',
                      icon: 0,
                      skin:'layui-layer-lan', //The skin is expanded by layer.mining.com. For skin extension rules, go here
                    });
                }
            else{
                    var reader = new FileReader();
                    reader.readAsDataURL(file); 
                    reader.onload=function(e){
                    $image.attr("src",e.target.result)
                     $image.cropper('reset', true).cropper('replace',e.target.result);
                    }
                    if(($('#target').attr('src').length) != 0){
                         $('#preview').show()
                         $('#preview-pane').show()
                         $('.crop-operate').show()
                    } 
                }
          })
            $image.cropper({
                        dragMode: 'move',
                        viewMode:3,
                        aspectRatio:1,//1 / 1, / / picture scale, 1:1
                        minCropBoxWidth:300,
                        minCropBoxHeight:300,
                        minContainerWidth:300,
                        minContainerHeight:300,
                        restore: false,
                        guides: false,
                        center: false,
                        highlight: false,
                        cropBoxMovable: false,
                        cropBoxResizable: false,
                        toggleDragModeOnDblclick: false,
                        modal:false,
                        responsive:false,
                        preview:'.preview-container',
                        background:false,     
                     });

 $('#thumb_upload').submit(function(){
      event.preventDefault();  
      // Get base64 of cut image
     var $imgData=$image.cropper('getCroppedCanvas')
      var dataurl = $imgData.toDataURL('image/jpeg');
     // Convert base64 to blob format
      var b64 = dataurl.split(',')[1];
     var binary = atob(b64);
     var array = [];
     for (var i = 0; i < binary.length; i++) {
         array.push(binary.charCodeAt(i));
     }
     var blob =  new Blob([new Uint8Array(array)], {type: 'image/jpeg'})
     // Using FormData() to make ajax request and upload pictures
     var formData = new FormData()
     // Picture name
     var img_name = new Date().getTime()+'.jpg';
     formData.append('csrfmiddlewaretoken','{{ csrf_token }}')
     formData.append('uploadFile',blob,img_name)
     var data = formData
      $.ajax({
           url: "/Upload address/",
           type: "post",
           dataType: "json",
           data:data,
           processData: false,
           contentType:false,
           success:function(result){
               if(result['state']==0){
                    layer.close(layer.index);  
                    window.parent.location.reload();
               }
               if(result['state']==1){
                     layer.alert('Upload failure,Please contact customer service', {
                          title:'Tips',
                          icon: 0,
                          skin: 'layui-layer-lan'//The skin is expanded by layer.mining.com. For skin extension rules, go here
                        },
                          function (){
                             window.parent.location.reload()
                        }
                    );      
               }
           }
      });
  });

  $('#cancel').click(function(){
      event.preventDefault();
      var index = parent.layer.getFrameIndex(window.name);  
      parent.layer.close(index);  
  })

</script>   

django background:

    def post(self,request):
        try:
            id =request.user.id
            #  Get database
            user = user.objects.get(id=id)
            #  Uploaded pictures
            thumb_file = request.FILES['uploadFile']
            user.picture = thumb_file
            user.save()
            to_json_response = {
                        'state':0
                        }
        except Exception as e:
            print(e)
            to_json_response={
                    'state':1
                }
        return HttpResponse(json.dumps(to_json_response), content_type='application/json')

Posted by Chinese on Thu, 02 Apr 2020 22:24:03 -0700