I have try implement react-image-cropper in my react.js project. But Image not load to show for crop issue.
Here I select the image using onSelectFile() function it take file but ReactCrop not load to image for cropper
Here the way I added the react-image-cropper
import React, { useState, useRef } from "react";
import ReactCrop from "react-image-crop";
import "react-image-crop/dist/ReactCrop.css";
import "./App.css";
function App() {
const [src, setSrc] = useState(null);
const [crop, setCrop] = useState({
unit: "%",
x: 0,
y: 0,
width: 50,
height: 50,
});
const [croppedImageUrl, setCroppedImageUrl] = useState(null);
const imageRef = useRef(null);
const onSelectFile = (e) => {
if (e.target.files && e.target.files.length > 0) {
const reader = new FileReader();
reader.addEventListener("load", () => {
setSrc(reader.result);
// Reset the crop to default values when a new image is selected
setCrop({
unit: "%",
x: 0,
y: 0,
width: 50,
height: 50,
});
});
reader.readAsDataURL(e.target.files[0]);
}
};
const onImageLoaded = (image) => {
imageRef.current = image;
};
const onCropComplete = (crop) => {
makeClientCrop(crop);
};
const onCropChange = (crop) => {
setCrop(crop);
};
const makeClientCrop = async (crop) => {
if (imageRef.current && crop.width && crop.height) {
const croppedImageUrl = await getCroppedImg(
imageRef.current,
crop,
"newFile.jpeg"
);
setCroppedImageUrl(croppedImageUrl);
}
};
const getCroppedImg = (image, crop, fileName) => {
const canvas = document.createElement("canvas");
const scaleX = image.naturalWidth / image.width;
const scaleY = image.naturalHeight / image.height;
canvas.width = crop.width;
canvas.height = crop.height;
const ctx = canvas.getContext("2d");
ctx.drawImage(
image,
crop.x * scaleX,
crop.y * scaleY,
crop.width * scaleX,
crop.height * scaleY,
0,
0,
crop.width,
crop.height
);
return new Promise((resolve) => {
canvas.toBlob((blob) => {
if (!blob) {
console.error("Canvas is empty");
return;
}
blob.name = fileName;
if (croppedImageUrl) {
window.URL.revokeObjectURL(croppedImageUrl);
}
const imageUrl = window.URL.createObjectURL(blob);
setCroppedImageUrl(imageUrl);
resolve(imageUrl);
}, "image/jpeg");
});
};
return (
<div className="App">
<div>
<input type="file" accept="image/*" onChange={onSelectFile} />
</div>
{src && (
<ReactCrop
src={src}
crop={crop}
ruleOfThirds
onImageLoaded={onImageLoaded}
onComplete={onCropComplete}
onChange={onCropChange}
/>
)}
{croppedImageUrl && (
<img alt="Crop" style={{ maxWidth: "100%" }} src={croppedImageUrl} />
)}
</div>
);
}
export default App;
Please provide the relevant solutions to me, thanks in advance
3
Answers
I think it’s because you have to create an image, as in this example:
The
<ReactCrop>
component doesn’t have asrc
property. You need to wrap it around an<img />
.Additionally, if you want to display a preview of the cropped image, you can draw the image directly to a canvas element ref.
Below is a simplified, annotated example.
evt.target.files
is always going to be an Array, even if it’s empty. so checking forevt.target.files
is unnecessary.
using the async FileReader API is also legacy, unnecessary and should be avoided.
converting things into base64 introduce a lot of overhead by converting the binary data into a string
and then back into binary data again.
a ObjectURL is just a pointer to where the file is located on the disc and reads faster and use less memory.