troubleshooting Question

How do I use cropper.js to create multiple dynamic crop windows over the same image

Avatar of mike99c
mike99c asked on
CSSHTMLPHPjQuery
5 Comments1 Solution22 ViewsLast Modified:
I’m creating a web application that takes a user submitted image and uploads two cropped images of different aspect ratios based on user selection.
 
It's documented that cropper.js supports multiple crops in the same window and I would like to know if it's possible (and if so how) to display two cropping windows over the same image. Ideally a user should be able to upload an image at two different crops by adjusting two different viewports on a single image and crop both at the same time, as illustrated below.


I’ve included sample code that supports single cropping and has been expanded to support multiple crops by refreshing the window with a new cropper. This approach involves displaying and submitting the crop twice as illustrated below.


The sample code below is a simple web page containing a button to upload a valid image for the user to crop.

Index.html
<!DOCTYPE html>
<html>
<head>
    <title>PHP Crop Image Before Upload using Cropper JS</title>
    <meta name="_token" content="{{ csrf_token() }}">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.js" i</script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.min.css" crossorigin="anonymous" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/js/bootstrap.min.js" </script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.6/cropper.css" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.6/cropper.js" i</script>
</head>
<style type="text/css">
img {
  display: block;
  max-width: 100%;
}
.preview {
  overflow: hidden;
  width: 160px; 
  height: 160px;
  margin: 10px;
  border: 1px solid red;
}
.modal-lg{
  max-width: 1000px !important;
}
</style>
<body>
<div class="container">
  <h1>PHP Crop Image Before Upload using Cropper JS</h1>
  <form method="post">
  <input type="file" name="image" class="image">
  </form>
  <br />
  <div id="uploaded_image"></div>
</div>

<div class="modal fade" id="modal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true">
  <div class="modal-dialog modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title" id="modalLabel">Single Crop</h5>
        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true"></span>
        </button>
      </div>
      <div class="modal-body">
        <div class="img-container">
            <div class="row">
                <div class="col-md-8">
                    <img id="image" src="https://avatars0.githubusercontent.com/u/3456749">
                </div>
                <div class="col-md-4">
                    <div class="preview"></div>
                </div>
            </div>
        </div>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
        <button type="button" class="btn btn-primary" id="crop">Crop</button>
      </div>
    </div>
  </div>
</div>

</div>
</div>
<script>

var $modal = $('#modal');
var image = document.getElementById('image');
var cropper;
  
$("body").on("change", ".image", function(e){
    var files = e.target.files;
    var done = function (url) {
      image.src = url;
      $modal.modal('show');
    };
    var reader;
    var file;
    var url;

    if (files && files.length > 0) {
      file = files[0];

      if (URL) {
        done(URL.createObjectURL(file));
      } else if (FileReader) {
        reader = new FileReader();
        reader.onload = function (e) {
          done(reader.result);
        };
        reader.readAsDataURL(file);
      }
    }
});

$modal.on('shown.bs.modal', function () {
    cropper = new Cropper(image, {
    aspectRatio: 4/5,
    viewMode: 3,
    preview: '.preview'
    });
    
}).on('hidden.bs.modal', function () {
   cropper.destroy();
   cropper = null;
  
});

$("#crop").click(function(){
    canvas = cropper.getCroppedCanvas({
      width: 600, // Adjust here
      height: 600,
    });

    canvas.toBlob(function(blob) {
        url = URL.createObjectURL(blob);
        var reader = new FileReader();
         reader.readAsDataURL(blob); 
         reader.onloadend = function() {
            var base64data = reader.result;  
            
            $.ajax({
                type: "POST",
                dataType: "json",
                url: "upload.php",
                data: {image: base64data},
                success: function(data){
                    console.log(data);
                    
                    $modal.modal('hide');
                    
                    $("#uploaded_image").html(data);
                   
                }
              });
         }
    });
})

</script>
</body>
</html>

Open in new window

upload.php
<?php

if(isset($_POST["image"]))
{

        $folderPath = 'upload/';

        $image_parts = explode(";base64,", $_POST['image']);
        $image_type_aux = explode("image/", $image_parts[0]);
        $image_type = $image_type_aux[1];
        $image_base64 = base64_decode($image_parts[1]);
        $file = $folderPath . uniqid() . '.png';

        file_put_contents($file, $image_base64);
     

        echo json_encode(["image uploaded successfully."]);
}
?>

Open in new window


Using cropper.js the script displays a cropper canvas with the submitted image.

The user can drag, move and select an area of fixed aspect ratio to crop.

When the crop button is selected, the crop is taken from the image and uploaded.  

This process could be repeated for multiple aspect ratios by destroying the cropper canvas and creating a new one with the same original image.  

How could this program be expanded to support the cropping of multiple images, is there an alternative library that is better suited for this implementation and is this the most viable solution for a better user experience?
ASKER CERTIFIED SOLUTION
mike99c

Our community of experts have been thoroughly vetted for their expertise and industry experience.

Log in to continue reading
Become an EE member today7-DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform for $9.99/mo
View membership options
Unlock 1 Answer and 5 Comments.
or
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.
See how we're fighting big data
The Value of Experts Exchange in My Daily IT Life

Experts Exchange (EE) has become my company's go-to resource to get answers. I've used EE to make decisions, solve problems and even save customers. OutagesIO has been a challenging project and... Keep reading >>

Mike

Owner of Outages.IO
Phoenix, Arizona, United States
Member Since 2016
Join a full scale community that combines the best parts of other tools into one platform.
Unlock 1 Answer and 5 Comments.
View membership options
“All of life is about relationships, and EE has made a virtual community a real community. It lifts everyone's boat.”
William Peck

Member since 2004