I have used the Croppie library to crop an image, with the viewport set to 225 x 225 pixels. Below is the code I wrote for this functionality:
$(document).ready(function() {
var $imageCrop;
var backgroundColor = 'rgb(232, 226, 230)'; // Default background color
function initializeCroppie(container) {
$imageCrop = $(container).croppie({
viewport: {
width: 225,
height: 225,
type: 'circle' // Set the viewport type to 'circle'
},
boundary: {
width: 300,
height: 300
},
showZoomer: true,
enableOrientation: true, // Allow image rotation
enforceBoundary: false, // Allow the image to be moved beyond the boundary
enableResize: false, // Allow resizing of the viewport
zoom: 1
});
// Set the background color of the extra space outside the image
$(container).find('.cr-boundary').css('background-color', backgroundColor);
}
$('#upload').on('change', function() {
if (this.files && this.files[0]) {
var reader = new FileReader();
reader.onload = function(e) {
Swal.fire({
title: 'Crop Image',
html: '<div id="cropContainer"><div id="image"></div></div>',
showCancelButton: true,
confirmButtonText: 'Crop Image',
didOpen: function() {
initializeCroppie('#image');
// Bind the resized image
$imageCrop.croppie('bind', {
url: e.target.result
}).then(function() {
console.log('Image uploaded and binding complete.');
// Extract the background color from 1px from the right edge of the resized image
var img = new Image();
img.src = e.target.result;
img.onload = function() {
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
canvas.width = img.width;
canvas.height = img.height;
// Draw the image onto the canvas
ctx.drawImage(img, 0, 0);
// Get the pixel data for 1px from the right edge (top edge of the image)
var pixelColor = ctx.getImageData(img.width - 1, 0, 1, 1).data;
// Compute color from the pixel
var r = pixelColor[0];
var g = pixelColor[1];
var b = pixelColor[2];
backgroundColor = `rgb(${r}, ${g}, ${b})`;
// Update Croppie boundary background color
$('#cropContainer .cr-boundary').css('background-color', backgroundColor);
console.log('Extracted Background Color:', backgroundColor);
};
});
},
preConfirm: function() {
return new Promise(function(resolve) {
$imageCrop.croppie('result', {
type: 'canvas',
size: { width: 225, height: 225 }
}).then(function(response) {
resolve(response);
});
});
}
}).then(function(result) {
if (result.isConfirmed) {
// Set the result image
$('#imgSrc').attr('src', result.value);
}
});
};
reader.readAsDataURL(this.files[0]);
// Reset the file input to allow re-uploading the same file
$(this).val('');
}
});
});
.swal2-modal {
width: 90%;
max-width: none;
}
.croppie-container {
height: 300px;
}
/* Set the background color of the extra space outside the image */
#cropContainer .cr-boundary {
background-color: rgb(232, 226, 230); /* Default color */
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/croppie/2.6.5/croppie.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/sweetalert2.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/croppie/2.6.5/croppie.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/sweetalert2.all.min.js"></script>
<div class="container mt-5">
<input type="file" id="upload" class="form-control">
<img src="" id="imgSrc" class="mt-3" />
</div>
While this generally works, I occasionally encounter an issue where the cropped area displayed in the viewport does not match the resulting image. This inconsistency typically occurs on the first attempt, or occasionally when the image resolution is higher. Attached below is a sample photo illustrating the issue.
Could someone help me identify the cause and provide a solution for this problem?