Reputation: 31
I'm trying to get the cropped image with react-image-crop module (blob). However I've problem with canvas, I guess it needs to be done asynchronously, but I'm not sure and I'm not sure if I've choosen the right approach either.
I've tried to do the same as written in documentation of react-image-crop in https://www.npmjs.com/package/react-image-crop. I'm also trying to do the same as Stefan in this topic: Get cropped image via react-image-crop module
state = {
image: '',
crop: {
aspect: 4/3,
x: 10,
y: 10,
width: 80,
height: 80,
},
imgSrc: null
}
getCroppedImg = (image, pixelCrop, fileName) => {
const canvas = document.createElement('canvas');
canvas.width = pixelCrop.width;
canvas.height = pixelCrop.height;
const ctx = canvas.getContext('2d');
ctx.drawImage(
image,
pixelCrop.x,
pixelCrop.y,
pixelCrop.width,
pixelCrop.height,
0,
0,
pixelCrop.width,
pixelCrop.height
);
// As a blob
return new Promise((resolve, reject) => {
canvas.toBlob(blob => {
blob.name = fileName;
resolve(blob);
}, 'image/jpeg');
});
}
handleImageUpload = e => {
const uploadData = new FormData();
uploadData.append("image", this.state.imgSrc);
service.handleUpload(uploadData)
.then(response => {
this.setState({ image: response.secure_url });
})
.catch(err => {
console.log("Error while uploading the file: ", err);
});
}
handleImagePreview = e => {
this.setState({image: URL.createObjectURL(e.target.files[0]), imgSrc: e.target.files[0]})
}
handleOnCropComplete = (crop, pixelCrop) => {
this.getCroppedImg(this.state.imgSrc, pixelCrop, 'preview.jpg')
.then((res) => {
const blobUrl = URL.createObjectURL(res);
console.log(blobUrl);
})
}
render() {
return(
<>
<input required onChange={this.handleImagePreview} type="file" />
<div className="crop-div">
<ReactCrop
src={this.state.image}
crop={this.state.crop}
onChange={this.handleOnCropChange}
onComplete={this.handleOnCropComplete} />
<button className="submit-btn" onClick={this.handleImageUpload}>Crop the image</button>
</div>
</>
)
}
After resizing the cropped area on the image I'll get this error:
"TypeError: Failed to execute 'drawImage' on 'CanvasRenderingContext2D': The provided value is not of type '(CSSImageValue or HTMLImageElement or SVGImageElement or HTMLVideoElement or HTMLCanvasElement or ImageBitmap or OffscreenCanvas)'"
Image that I'm passing is Image File Object.
Upvotes: 3
Views: 3413
Reputation: 97672
A file object isn't in the list expected as stated by the error message, so you have to create an object in the list from the object you have.
In this case we'll use the HTMLImageElement.
getCroppedImg = (imageFile, pixelCrop, fileName) => {
const canvas = document.createElement('canvas');
canvas.width = pixelCrop.width;
canvas.height = pixelCrop.height;
const ctx = canvas.getContext('2d');
var image = new Image();
var promise = new Promise((resolve, reject) => {
image.onload = function(){
ctx.drawImage(
image,
pixelCrop.x,
pixelCrop.y,
pixelCrop.width,
pixelCrop.height,
0,
0,
pixelCrop.width,
pixelCrop.height
);
resolve();
};
image.src = URL.createObjectURL(imageFile);
}).then(function(){
return new Promise((resolve, reject) => {
canvas.toBlob(blob => {
blob.name = fileName;
resolve(blob);
}, 'image/jpeg');
});
});
return promise;
}
Upvotes: 4