MIF_E31230910_MP-HRIS-WEB/public/js/image-cropper.js

176 lines
5.8 KiB
JavaScript

/**
* Image Cropper - Profile Photo
* Menggunakan Cropper.js untuk crop foto profil berbentuk lingkaran
*/
document.addEventListener('DOMContentLoaded', function () {
const fotoInput = document.getElementById('foto-input');
const cropModal = document.getElementById('crop-modal');
const cropImage = document.getElementById('crop-image');
const cropSaveBtn = document.getElementById('crop-save-btn');
const cropCancelBtn = document.getElementById('crop-cancel-btn');
const cropRotateLeftBtn = document.getElementById('crop-rotate-left');
const cropRotateRightBtn = document.getElementById('crop-rotate-right');
const cropResetBtn = document.getElementById('crop-reset');
const cropZoomInBtn = document.getElementById('crop-zoom-in');
const cropZoomOutBtn = document.getElementById('crop-zoom-out');
let cropper = null;
if (!fotoInput || !cropModal) return;
fotoInput.addEventListener('change', function (e) {
const file = e.target.files[0];
if (!file) return;
if (!file.type.startsWith('image/')) {
alert('File harus berupa gambar.');
fotoInput.value = '';
return;
}
const reader = new FileReader();
reader.onload = function (event) {
cropImage.src = event.target.result;
cropModal.classList.remove('hidden');
if (cropper) {
cropper.destroy();
}
setTimeout(function () {
cropper = new Cropper(cropImage, {
aspectRatio: 1,
viewMode: 1,
dragMode: 'move',
autoCropArea: 0.85,
cropBoxResizable: false,
cropBoxMovable: false,
guides: false,
center: true,
highlight: false,
background: false,
responsive: true,
restore: false,
checkCrossOrigin: false,
ready: function () {
const containerData = cropper.getContainerData();
const size = Math.min(containerData.width, containerData.height) * 0.8;
cropper.setCropBoxData({
left: (containerData.width - size) / 2,
top: (containerData.height - size) / 2,
width: size,
height: size,
});
},
});
}, 100);
};
reader.readAsDataURL(file);
});
if (cropRotateLeftBtn) {
cropRotateLeftBtn.addEventListener('click', function () {
if (cropper) cropper.rotate(-90);
});
}
if (cropRotateRightBtn) {
cropRotateRightBtn.addEventListener('click', function () {
if (cropper) cropper.rotate(90);
});
}
if (cropResetBtn) {
cropResetBtn.addEventListener('click', function () {
if (cropper) cropper.reset();
});
}
if (cropZoomInBtn) {
cropZoomInBtn.addEventListener('click', function () {
if (cropper) cropper.zoom(0.1);
});
}
if (cropZoomOutBtn) {
cropZoomOutBtn.addEventListener('click', function () {
if (cropper) cropper.zoom(-0.1);
});
}
cropSaveBtn.addEventListener('click', function () {
if (!cropper) return;
cropSaveBtn.disabled = true;
cropSaveBtn.innerHTML = `
<svg class="animate-spin h-4 w-4 mr-2" viewBox="0 0 24 24" fill="none">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"></path>
</svg>
Memproses...
`;
const canvas = cropper.getCroppedCanvas({
width: 512,
height: 512,
fillColor: '#fff',
imageSmoothingEnabled: true,
imageSmoothingQuality: 'high',
});
canvas.toBlob(function (blob) {
const croppedFile = new File([blob], 'profile-photo.jpg', {
type: 'image/jpeg',
});
const dataTransfer = new DataTransfer();
dataTransfer.items.add(croppedFile);
fotoInput.files = dataTransfer.files;
const preview = document.getElementById('preview-foto');
const previewNew = document.getElementById('preview-foto-new');
const placeholder = document.getElementById('placeholder-foto');
const url = URL.createObjectURL(blob);
if (preview) {
preview.src = url;
} else {
if (placeholder) placeholder.classList.add('hidden');
if (previewNew) {
previewNew.src = url;
previewNew.classList.remove('hidden');
}
}
closeCropModal();
}, 'image/jpeg', 0.9);
});
cropCancelBtn.addEventListener('click', function () {
fotoInput.value = '';
closeCropModal();
});
cropModal.addEventListener('click', function (e) {
if (e.target === cropModal) {
fotoInput.value = '';
closeCropModal();
}
});
function closeCropModal() {
cropModal.classList.add('hidden');
if (cropper) {
cropper.destroy();
cropper = null;
}
cropSaveBtn.disabled = false;
cropSaveBtn.innerHTML = `
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
Simpan
`;
}
});