import Cropper from "react-easy-crop"; import { useState, useCallback, useRef } from "react"; export default function ImageUploader({target, id, buttonMsg, handleAvatarChange, imageRef}){ const imageFileRef = useRef(); const [imageDataUrl, setImageDataUrl] = useState(); const [croppedAreaPixels, setCroppedAreaPixels] = useState(); const [rotation] = useState(1); const [crop, setCrop] = useState({ x: 0, y: 0 }) const [zoom, setZoom] = useState(1) const [imageLoaded, setImageLoaded] = useState(false); const [isImageShown, setIsImageShown] = useState(false); const [shownImage, setShownImage] = useState(); const [imageUploadModalOpen, setImageUploadModalOpen] = useState(false); // TODO // PUSH cropped image to the database in column = target const openUploaderModal = () => { imageRef ? (setIsImageShown(true), setShownImage(imageRef)) : setIsImageShown(false) setImageUploadModalOpen(!imageUploadModalOpen) } const closeImageUploadModal = () => { setImageUploadModalOpen(false); }; async function ImageUploadHandler() { console.log(imageFileRef.current.files[0]); const img = await readFile(imageFileRef.current.files[0]); console.log(img); setImageDataUrl(img); CropHandler(); } const readFile = (file) => { return new Promise((resolve) => { const reader = new FileReader() reader.addEventListener('load', () => resolve(reader.result), false) reader.readAsDataURL(file) }) } const onCropComplete = useCallback((croppedArea, croppedAreaPixels) => { setCroppedAreaPixels(croppedAreaPixels) }, []) const CropHandler = () => { setCrop({ x: 0, y: 0 }); setZoom(1); setImageLoaded(true); } const createImage = (url) => new Promise((resolve, reject) => { const image = new Image() image.addEventListener('load', () => resolve(image)) image.addEventListener('error', error => reject(error)) image.setAttribute('crossOrigin', 'anonymous') // needed to avoid cross-origin issues on CodeSandbox image.src = url }) function getRadianAngle(degreeValue) { return (degreeValue * Math.PI) / 180 } async function getCroppedImg(imageSrc, pixelCrop, rotation = 0) { const image = await createImage(imageSrc) const canvas = document.createElement('canvas') const ctx = canvas.getContext('2d') const maxSize = Math.max(image.width, image.height) const safeArea = 2 * ((maxSize / 2) * Math.sqrt(2)) // set each dimensions to double largest dimension to allow for a safe area for the // image to rotate in without being clipped by canvas context canvas.width = safeArea canvas.height = safeArea // translate canvas context to a central location on image to allow rotating around the center. ctx.translate(safeArea / 2, safeArea / 2) ctx.rotate(getRadianAngle(rotation)) ctx.translate(-safeArea / 2, -safeArea / 2) // draw rotated image and store data. ctx.drawImage( image, safeArea / 2 - image.width * 0.5, safeArea / 2 - image.height * 0.5 ) const data = ctx.getImageData(0, 0, safeArea, safeArea) // set canvas width to final desired crop size - this will clear existing context canvas.width = pixelCrop.width canvas.height = pixelCrop.height // paste generated rotate image with correct offsets for x,y crop values. ctx.putImageData( data, Math.round(0 - safeArea / 2 + image.width * 0.5 - pixelCrop.x), Math.round(0 - safeArea / 2 + image.height * 0.5 - pixelCrop.y) ) // As Base64 string return canvas.toDataURL('image/jpeg'); // As a blob // return new Promise(resolve => { // canvas.toBlob(file => { // resolve(URL.createObjectURL(file)) // }, 'image/jpeg') // }) } const showCroppedImage = useCallback(async () => { try { const croppedImage = await getCroppedImg( imageDataUrl, croppedAreaPixels, rotation ) setIsImageShown(true) setShownImage(croppedImage) setImageLoaded(false) handleAvatarChange(croppedImage) closeImageUploadModal() } catch (e) { console.error(e) } }, [croppedAreaPixels, rotation]) return (
{ imageUploadModalOpen &&
{!imageLoaded &&
{!isImageShown &&

No {target}

} {isImageShown && {target} }
} {imageLoaded &&
}
}
) }