During an exam project i wanted product images for a point of sale module i developed for a restaurant. The main problem was the size of the images, they where either too large or in a wrong format (4:3 or 16:9). So i decided to find out what other developers did i order to be sure that the uploaded images met the correct requirements.

Once i started looking i found something called Cropper JS. The benefit when using cropper JS is that the JavaScript and design is mobile responsive, which allows for usage by mobile devices.

It is my first time using this library and i must say i am impressed but the functionality and that it’s free to use! The sole purpose for adding this library to my project was, as i mentioned earlier, that i needed a way of making sure that the added images was in the correct size.

Below is the result of adding the library to my project in combination with a modal.

How to crop images using Cropper.js a Javascript Image Cropper 1
Cropping an image for the product

As you can see i still got a little issue with the styling. I am not that much of a frontend designer and as long as this project is not for sale, I won’t concentrate about fixing the columns width for this modal.

The blue box surrounding the image is the new size of the image. Using the built in functionality of Cropper.JS it’s possible to predefine a minimum and maximum size for the image to be cropped. This makes the library perfect for solving my problem.

Cropper JS Modes

Before i will show you how i implemented the cropper in my project, i wan’t to talk a little about the viewmodes. They where a bit confusing in the beginning, but after af few examples i managed to be pretty confident using the library and adding a nice solution to the final application.

  • Viewmode 0 – This mode will set no restrictions for the image crop selection. This allows the user to select area outside the image, which will generate som black borders, if the aspect ratio is not correct. I used this viewmode in my project.
  • Viewmode 1 – A great mode if you want to lock or restrict the option to select the crop area outside the canvas.
  • Viewmode 2 – If you use this mode it will restrict the minimum canvas size to fit within your container. This is a great choice if you want to specify minimum canvas for the cropping. As a result the canvas around the images will be surrounded by extra space.
  • Viewmode 3 – This mode allows you to restrict the minimum canvas size to fill the container.

Cropper JS example using Laravel Framework

I won’t go into details about how to write the controller and implementing the styling and javascripts for the modal. This example will only be for adding a modal with the cropper. The example will make use of two blade files a create.blade.app and a cropper.blade.app. Both files are included below:

create.blade.app

@extends('layouts.app')

@section('content')
    @include("backend.products/cropper")
    <!-- Image cropper -->
    <script src="{{url('assets/js/plugins/cropper/cropper.js')}}"></script>

    <link href="{{url('assets/css/plugins/cropper/cropper.css')}}" rel="stylesheet">

    <!-- Content -->
    <div class="content">
        <!-- Animated -->
        <div class="animated fadeIn">
            <div class="row">
                            <div class="col-lg-4">
                                <form id="uploadimage" action="" method="post" enctype="multipart/form-data">
                                    <input type="hidden" name="cropped_value" id="cropped_value" value="">
                                    <label title="Upload image file" for="inputImage" class="">
                                        <div class="upload-pic img-circle" style="">
                                            <img id="image_source" class="img-circle" src="" alt="">
                                        </div>
                                        <div class="upload-pic-new btn btn-primary text-center">
                                            <input type="file" name="file" id="cropper" style="display:none"/>
                                            <label for="cropper">
                                                <div class="pic-placeholder">
                            <span class="upload_button"> <i class="fa fa-picture-o"></i>
                            Upload image </span>
                                                </div>
                                            </label>
                                        </div>
                                </form>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <style>
        .cropper-container.cropper-bg {
            background: #fff !important;
            background-image: none !important;
        }

        .cropper-modal {
            opacity: .5;
            background-color: #fff;
        }

        .upload-pic {
            height: 200px;
            width: 200px;
            background: #ccc;
            margin: 10px;
        }

        .upload_button {
            margin-top: 10px;
        }

    </style>
@endsection

I the beginning of the create file i added an include for the cropper.blade.app file. I have also added the two requirements for using the cropper.js library both styling and functionality.

The modal will be launched from the cropper file, when clicking the Upload image button. Also i added some styling for the modal, as i wanted to modify a little on how the modal looks like (only for user experience).

cropper.blade.app

<link href="{{ asset('assets/dist/cropper.css')}}" rel="stylesheet">
<script src="{{ asset('assets/dist/cropper.js') }}"></script>
<style>
    .cropper-container.cropper-bg {
        background: #fff !important;
        background-image: none !important;
    }

    .cropper-modal {
        opacity: .5;
        background-color: #fff;
    }

    /*.modal-body { padding-left:0px; padding-right:0px;}*/

</style>
<script>

    $(function () {
        var cropper;

        // Adding options for the container size for the given image.
        // This was a smart options as i only wanted to add images in a specific size
        var options = {
            aspectRatio: 1 / 1,
            minContainerWidth: 550,
            minContainerHeight: 250,
            minCropBoxWidth: 250,
            minCropBoxHeight: 250,
            cropBoxResizable: false,
            scalable: false,
            crop: function (e) {
                $("#cropped_value").val(parseInt(e.detail.width) + "," + parseInt(e.detail.height) + "," + parseInt(e.detail.x) + "," + parseInt(e.detail.y) + "," + parseInt(e.detail.rotate));
            },
            ready: function () {
                $("#image_loader").html('');
            }
        };



        $("body").on("click", "#image_source", function () {

            // Get the image for cropping
            var src = $("#image_source").attr("src");
            src = src.replace("/thumb", "");

            $('#image_cropper').attr('src', src);

            // Trigger the modal to show up upon image has been uploaded to the server
            $("#myModal").modal("show");

        });

        // Option to remove modal and cropper when click on cancel
        $(".modal").on("hide.bs.modal", function () {
            // $(".cropper-container").remove();
            // cropper.destroy();
            var src = $("#image_source").attr("src");
            src = src.replace("/thumb", "");
            $('#image_cropper').attr('src', src);
            cropper.replace(src);


        });
        $(".modal").on("show.bs.modal", function () {

            if ($("#check_cropper").val() != 1) {
                $("#image_loader").html('<i class="fa fa-spinner fa-spin " style="font-size:36px;color:#f79426"></i>');
                // Returns the image that has the image_cropper ID from the HTML DOM.
                var image = document.getElementById('image_cropper');

                // Create a new cropper object
                cropper = new Cropper(image, options);
                $("#check_cropper").val(1);
            }
        });

        // Option for rotating the image if needed
        $("body").on("click", ".rotate", function () {
            var degree = $(this).attr("data-option");
            cropper.rotate(degree);
        });

        // Save the image
        $("body").on("click", "#Save", function () {

            // The image will be stored in an array with key -> value
            var form_data = $('#uploadimage')[0];

            // Show a spinner on saving image
            $("#loader").html('<i class="fa fa-spinner fa-spin " style="font-size:24px;color:#f79426"></i>');

            $("#Save").prop("disabled", true);

            // Using ajax for uploading and storing the image to the Laravel application
            $.ajax({
                url: "<?php echo url('product/upload_photo_crop'); ?>", // Url to request for storing image
                type: "POST",
                mimeType: "multipart/form-data",
                headers: {
                    'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
                },            

                // Type of request to be send, called as method
                data: new FormData(form_data), // Data sent to server, a set of key/value pairs (i.e. form fields and values)
                contentType: false,       // The content type used when sending data to the server.
                cache: false,             // To unable request pages to be cached
                processData: false,        // To send DOM Document or non processed data file it is set to false
                success: function (res)   // If the images was saved, call this function
                {
                    var num = Math.random();
                    res = res + "?v=" + num;
                    $('#image_source,#image,#user_pro_image').attr('src', res);

                    $("#loader").html('');
                    $("#Save").prop("disabled", false);
                    $("#myModal").modal("hide");
                    $('.upload-pic,.choose-profile-pic,#image_preview').show();
                    $(document).find('#js_image_exists').val(1);
                }
            });
        });
    });
</script>
<style>
    img {
        max-width: 100%;
    }
</style>

<!-- Adding the modal opening triggered by the JavaScript above -->

<div id="myModal" class="modal fade  confirm-modal" role="dialog">
    <div class="modal-dialog">

        <!-- Modal content-->
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal">×</button>
                <h4 class="modal-title">Add Image</h4>
            </div>
            <div class="modal-body">
                <div>
                    <div width="100%" style="text-align:center" id="image_loader"></div>
                    <img width="100%" src="" id="image_cropper">
                    <br>
                    <p class="text-center">
                        <button type="button" class="btn btn-primary rotate" data-method="rotate" data-option="-30"><i
                                    class="fa fa-undo"></i></button>
                        <button type="button" class="btn btn-primary rotate" data-method="rotate" data-option="30"><i
                                    class="fa fa-repeat"></i></button>
                    </p>

                </div>
                <input type="hidden" id="check_cropper" value="0"/>

                <div class="modal-footer">


                    <input type="button" class="btn btn-primary" id="Save"
                           value="Save image">  </button>
                    <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
                </div>
            </div>
        </div>

    </div>
</div>

As you can see i have added a custom JavaScript code for suiting this cropper to my project. I have used the HTML DOM to return values when requested by ID in the JavaScript. Using the getElementById makes it easy to retrieve an image from the HTML form and handling it with the JavaScript in the cropper file.

The final result is shown below including the rotate functionality.

How to crop images using Cropper.js a Javascript Image Cropper 2
Using the cropper in a modal

Learning to use this library made i much easier for me to handle product images, and making sure that the images uploaded by product owner will be in the correct size. It took me some time and i watched a couple of videos on how to work with the cropper – especially the viewmodes was a bit confusing, but got them working when i learned how they worked. That’s also why i have added them above with a little description.

Leave a Reply