Hi All… I want to use cropperjs 1.6.2 and have got everything working the way i want except for 1 thing… the image being saved is not the cropped image… it is the original/holding image… my js is not great and the help so far has not fixed this issue… cropperjs 1.6.2 is here - https://fengyuanchen.github.io/cropperjs/ - here is my submit code so far:
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$filename = $_POST['filename'] ?? 'profile_photo.png';
$img = $_POST['croppedImage'] ?? '';
if ($img) {
$img = str_replace('data:image/png;base64,', '', $img);
$img = str_replace(' ', '+', $img);
$data = base64_decode($img);
// Save the image
$directory = '/home/website/public_html/images/account/profile-photos/';
$filePath = $directory . $filename;
// Ensure the directory exists
if (!is_dir($directory)) {
mkdir($directory, 0755, true);
}
if (file_put_contents($filePath, $data)) {
echo 'Image uploaded successfully.';
} else {
echo 'Failed to save the image.';
}
} else {
echo 'No cropped image data received.';
}
} else {
echo 'Invalid request.';
}
and here is my form and js:
<form id="cropperForm" action="index.php?action=missionControl&nav=missionControl&subnav=yourAccount&do=profile&process=save " method="post" enctype="multipart/form-data">
<input type="hidden" name="croppedImage" id="croppedImageInput">
<input type="hidden" name="filename" value="profile_photo.png">
<link rel="stylesheet" href="https://website.com/resources/general/web-functions/cropperjs/docs/css/cropper.css">
<link rel="stylesheet" href="https://website.com/resources/general/web-functions/cropperjs/docs/css/main.css">
<div>
<div class="container text-center">
<div class="row justify-content-center">
<div class="col-md-9">
<div class="docs-demo">
<div class="img-container" style="max-height: 400px;">
<img id="imageToCrop" src="https://website.com/resources/general/mission-control/website-account/images/user-holding.png">
</div>
</div>
</div>
</div>
<div class="row justify-content-center" id="actions">
<div class="col-md-12 docs-buttons d-flex justify-content-center flex-wrap">
<!-- Button Groups -->
<div class="btn-group">
<button type="button" class="btn btn-main-custom" data-method="zoom" data-option="0.1" title="Zoom In">
<span class="docs-tooltip" data-toggle="tooltip" title="Zoom In">
<span class="fa-light fa-magnifying-glass-plus"></span>
</span>
</button>
<button type="button" class="btn btn-main-custom" data-method="zoom" data-option="-0.1" title="Zoom Out">
<span class="docs-tooltip" data-toggle="tooltip" title="Zoom Out">
<span class="fa-light fa-magnifying-glass-minus"></span>
</span>
</button>
</div>
<div class="btn-group">
<button type="button" class="btn btn-main-custom" data-method="move" data-option="-10" data-second-option="0" title="Move Left">
<span class="docs-tooltip" data-toggle="tooltip" title="Move Left">
<span class="fa-duotone fa-light fa-arrow-left"></span>
</span>
</button>
<button type="button" class="btn btn-main-custom" data-method="move" data-option="10" data-second-option="0" title="Move Right">
<span class="docs-tooltip" data-toggle="tooltip" title="Move Right">
<span class="fa-duotone fa-light fa-arrow-right"></span>
</span>
</button>
<button type="button" class="btn btn-main-custom" data-method="move" data-option="0" data-second-option="-10" title="Move Up">
<span class="docs-tooltip" data-toggle="tooltip" title="Move Up">
<span class="fa-duotone fa-light fa-arrow-up"></span>
</span>
</button>
<button type="button" class="btn btn-main-custom" data-method="move" data-option="0" data-second-option="10" title="Move Down">
<span class="docs-tooltip" data-toggle="tooltip" title="Move Down">
<span class="fa-duotone fa-light fa-arrow-down"></span>
</span>
</button>
</div>
<div class="btn-group">
<button type="button" class="btn btn-main-custom" data-method="rotate" data-option="-45" title="Rotate Left">
<span class="docs-tooltip" data-toggle="tooltip" title="Rotate Left">
<span class="fa-light fa-arrow-rotate-left"></span>
</span>
</button>
<button type="button" class="btn btn-main-custom" data-method="rotate" data-option="45" title="Rotate Right">
<span class="docs-tooltip" data-toggle="tooltip" title="Rotate Right">
<span class="fa-light fa-arrow-rotate-right"></span>
</span>
</button>
</div>
<div class="btn-group">
<button type="button" class="btn btn-main-custom" data-method="scaleX" data-option="-1" title="Flip Horizontal">
<span class="docs-tooltip" data-toggle="tooltip" title="Flip Left/Right">
<span class="fa-light fa-arrows-left-right"></span>
</span>
</button>
<button type="button" class="btn btn-main-custom" data-method="scaleY" data-option="-1" title="Flip Vertical">
<span class="docs-tooltip" data-toggle="tooltip" title="Flip Up/Down">
<span class="fa-sharp fa-light fa-arrows-up-down"></span>
</span>
</button>
</div>
<div class="btn-group">
<label class="btn btn-main-custom btn-upload" for="inputImage" title="Upload image file">
<input type="file" class="sr-only" id="inputImage" name="file" accept="image/*">
<span class="docs-tooltip" data-toggle="tooltip" title="Upload Image">
<span class="fa-light fa-upload"></span>
</span>
</label>
</div>
</div>
<div class="col-md-3 docs-toggles"></div>
</div>
</div>
</div>
<style>
/* Ensure the crop area and preview are circular */
.cropper-view-box,
.cropper-face {
border-radius: 50%; /* Circular crop area */
}
</style>
<script src="https://unpkg.com/jquery@3/dist/jquery.slim.min.js" crossorigin="anonymous"></script>
<script src="https://website.com/resources/general/web-functions/cropperjs/docs/js/cropper.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
const Cropper = window.Cropper;
const image = document.getElementById('imageToCrop');
const inputImage = document.getElementById('inputImage');
const form = document.getElementById('cropperForm');
const croppedImageInput = document.getElementById('croppedImageInput');
let cropper;
let scaleX = 1; // Track horizontal flip
let scaleY = 1; // Track vertical flip
// Initialize Cropper.js
cropper = new Cropper(image, {
aspectRatio: 1, // Ensures square cropping, but will appear circular due to CSS
viewMode: 1, // Restrict crop to image boundaries
dragMode: 'move', // Allow moving the image
cropBoxResizable: false, // Fixed crop box size
cropBoxMovable: false, // Prevent moving crop box
toggleDragModeOnDblclick: false, // Disable toggling drag mode
ready: function () {
console.log('Cropper is ready.');
},
});
// Attach toolbar actions
document.querySelectorAll('[data-method]').forEach((button) => {
button.addEventListener('click', function () {
const method = this.getAttribute('data-method');
const option = this.getAttribute('data-option');
const secondOption = this.getAttribute('data-second-option');
if (cropper && method) {
if (method === 'scaleX') {
// Handle horizontal flip
scaleX = -scaleX;
cropper.scaleX(scaleX);
} else if (method === 'scaleY') {
// Handle vertical flip
scaleY = -scaleY;
cropper.scaleY(scaleY);
} else {
// Handle other actions
const parsedOption = option ? parseFloat(option) : undefined;
const parsedSecondOption = secondOption ? parseFloat(secondOption) : undefined;
if (parsedSecondOption !== undefined) {
cropper[method](parsedOption, parsedSecondOption);
} else {
cropper[method](parsedOption);
}
}
}
});
});
// Handle new image uploads
inputImage.addEventListener('change', function () {
const files = this.files;
if (files && files.length) {
const file = files[0];
if (/^image\/\w+/.test(file.type)) {
const uploadedImageURL = URL.createObjectURL(file);
image.src = uploadedImageURL;
image.onload = function () {
cropper.destroy(); // Destroy previous Cropper instance
cropper = new Cropper(image, {
aspectRatio: 1,
viewMode: 1,
dragMode: 'move',
cropBoxResizable: false,
cropBoxMovable: false,
toggleDragModeOnDblclick: false,
});
};
} else {
alert('Please choose a valid image file.');
}
}
});
// Handle form submission
form.addEventListener('submit', function (event) {
event.preventDefault();
if (cropper) {
const croppedCanvas = cropper.getCroppedCanvas({
width: 250,
height: 250,
fillColor: '#fff', // Background color for transparency
});
if (croppedCanvas) {
// Add Base64 cropped image to hidden input field
croppedImageInput.value = croppedCanvas.toDataURL('image/png');
// Submit the form
form.submit();
} else {
alert('Failed to generate cropped image.');
}
} else {
alert('Cropper is not initialized.');
}
});
});
</script>
<div style="padding-bottom:1em;"></div>
<div style="padding-bottom:1em;">
<button type="submit" class="btn btn-main-custom" style="width:100%;">
SAVE PROFILE PHOTO NOW <i class="fa-sharp fa-light fa-map-location"></i> <i class="fa-light fa-chevrons-right"></i>
</button>
</div>
</form>
Any help with this would be great… I have a feeling that this is a pretty easy fix if you know what to do.
mrmbarnes