So recently in one project there was requirement for Cropper JS with Slider. Once we started looking in google we found something similar called Croppie. But once we used it in our project then we realised that it’s not mobile responsive. So then there is no alternate of Cropper Js.
We have used this library in many projects and it has never disappointed us with it’s feature richness. But this situation was little different. we needed to have zoom slider just like twitter edit profile is providing which leads us to find a way around it with Cropper JS with slider.
So here is what we have made with Cropper JS.
Here you can see it will calculate slider value according to image orientation. So Image will never go under cropper box and vise-versa it will provide zoom level max to natural width of image.
Cropper JS Modes
So before we go further we need to understand cropper js modes. It’s quite confusing.
1)Viewmode = 0 : If you use it then there will be no restriction in image crop selection. User can select area of outside of the image if viewmode = 0 is used.
2) Viewmode = 1 : If you use then it will not allow to select crop area outside canvas. (In Most cases and purpose of this demo we have used viewmode 1)
3)Viewmode = 2 : If you use then it will restrict the minimum canvas size to fit within the container. If the proportions of the canvas and container are different than the minimum canvas will be surrounded by extra space in one of the dimensions.
4)Viewmode = 3 : If you use then it will restrict the minimum canvas size to fill fit the container. If the proportions of the canvas and container are different than the container will not be able to fit the whole canvas in one of the dimensions.
Let’s try to dive into the code
index.html
<html> <head> <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet"> <link href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" rel="stylesheet"> <link href="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.4.1/cropper.css" rel="stylesheet"> <link href="style.css" rel="stylesheet"> </head> <body> <div class="container"> <h1>Cropper with a range of aspect ratio</h1> <div> <input type="file" id="cropperfile" /> <br /> <br /> <div style="width:600px;height:400px;"> <img src="" id="cropper-img" /> </div> </div> <br /> <div id="zoom-slider"></div> <div class="row"> <div class="slider-val-area"> <span id="min-zoom-val" class="pull-left">0</span> </div> <div class="slider-val-area"> <span id="max-zoom-val" class="pull-right">1</span> </div> </div> </div> <script type="text/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script> <script type="text/javascript" src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui-touch-punch/0.2.3/jquery.ui.touch-punch.min.js"></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.4.1/cropper.js"></script> <script type="text/javascript" src="index.js"></script> </body> </html>
index.js Contains all javascript code for this demo
// Write Javascript code! var isInitialized = false; var cropper = ''; var file = ''; var _URL = window.URL || window.webkitURL; // Initialize Slider $(document).ready(function () { $("#cropperfile") .change(function (e) { if (file = this.files[0]) { var oFReader = new FileReader(); oFReader.readAsDataURL(file); oFReader.onload = function () { // Destroy the old cropper instance $("#cropper-img").attr('src', this.result); $('#cropper-img').addClass('ready'); if (isInitialized == true) { $('#zoom-slider').val(0); cropper.destroy(); } initCropper(); } } }); $("#zoom-slider").slider({ orientation: "horizontal", range: "min", max: 1, min: 0, value: 0, step: 0.0001, slide: function () { if (isInitialized == true) { if (cropper.canvasData.naturalWidth < 600 || cropper.canvasData.naturalHeight < 400) { event.preventDefault(); } else { var currentValue = $("#zoom-slider").slider("value"); var zoomValue = parseFloat(currentValue); cropper.zoomTo(zoomValue.toFixed(4)); } } } }); }); function initCropper() { var vEl = document.getElementById('cropper-img'); cropper = new Cropper(vEl, { viewMode: 1, dragMode: 'move', aspectRatio: 1.5, checkOrientation: false, cropBoxMovable: false, cropBoxResizable: false, zoomOnTouch: false, zoomOnWheel: false, guides: false, highlight: false, ready: function (e) { var cropper = this.cropper; cropper.zoomTo(0); var imageData = cropper.getImageData(); console.log("imageData ", imageData); var minSliderZoom = imageData.width / imageData.naturalWidth; $('#min-zoom-val').html(minSliderZoom.toFixed(4)); $(".cr-slider-wrap").show(); $("#zoom-slider").slider("option", "max", 1); $("#zoom-slider").slider("option", "min", minSliderZoom); $("#zoom-slider").slider("value", minSliderZoom); } }); isInitialized = true; }
So here is explanation of coding part for Cropper JS with slider.
Most of the code is understandable. Let’s understand few critical parts.
var imageData = cropper.getImageData();
var minSliderZoom = imageData.width / imageData.naturalWidth;
This the main part which calculates slider minimum value in a way that it won’t go insider cropper and slider will work fine. Here imageData.width is cropper box width and imageData.naturalWidth is Original Width of Image.
if (cropper.canvasData.naturalWidth < 600 || cropper.canvasData.naturalHeight < 400) { event.preventDefault();
} else {
var currentValue = $(“#zoom-slider”).slider(“value”);
var zoomValue = parseFloat(currentValue);
cropper.zoomTo(zoomValue.toFixed(4));
}
Here is Extra Condition which help us to restrict image size width x height to 600 x 400. In case it goes down slider will stop changing crop level automatically.
You can download this code from this GitHub Repo.
Also we have cropper js with slider here at Stackblitz