Black background when cropping image
lolottetheclash opened this issue · comments
lauren Olivier commented
Hello,
I read the same issue many times but the solution didn't work for me (saving as png instead of jpeg)
I show you my code:
import { Area } from 'react-easy-crop'
import { useState, useEffect } from 'react'
type Size = {
width: number
height: number
}
export const useCroppedImage = (
imageSrc: string,
croppedArea: Area | null,
requestedSize?: Size,
) => {
const [image, setImage] = useState<File | null>(null)
const [imageError, setImageError] = useState<Error | null>(null)
useEffect(() => {
if (!imageSrc || !croppedArea) {
setImage(null)
setImageError(null)
return
}
const createImage = async () => {
try {
const imageResult: File | null = await new Promise((resolve, reject) => {
const image = new Image()
image.src = imageSrc
image.onload = () => {
const canvas = document.createElement('canvas')
const canvasWidth = requestedSize?.width || croppedArea?.width
const canvasHeight = requestedSize?.height || croppedArea?.height
const scaleX = image.naturalWidth / image.width
const scaleY = image.naturalHeight / image.height
canvas.width = canvasWidth
canvas.height = canvasHeight
const ctx = canvas.getContext('2d')
if (ctx) {
croppedArea
? ctx?.drawImage(
image,
croppedArea.x * scaleX,
croppedArea.y * scaleY,
croppedArea.width * scaleX,
croppedArea.height * scaleY,
0,
0,
canvasWidth,
canvasHeight,
)
: ctx?.drawImage(image, 0, 0, canvasWidth, canvasHeight)
}
canvas.toBlob((blob) => {
if (!blob) {
reject(new Error('Created canvas is empty'))
return
}
const file = new File([blob], 'croppedImage.png', { type: 'image/png' })
resolve(file)
})
}
})
setImage(imageResult)
setImageError(null)
} catch (e: unknown) {
console.error(e instanceof Error ? e.message : 'An unexpected error happened')
setImageError(e instanceof Error ? e : new Error('An unexpected error happened'))
}
}
createImage()
}, [croppedArea, imageSrc, requestedSize])
return { image, imageError }
}
the cropper:
import { useCallback, useState } from 'react'
import Cropper, { Area } from 'react-easy-crop'
import { ImageCropProps, Point } from './ImageCropper.model'
import { SliderInput } from '../inputs/SliderInput/SliderInput.component'
import styles from './ImageCropper.module.scss'
import classNames from 'classnames'
export const ImageCropper = ({
src,
onCropComplete,
ratio = 1,
initialCrop = { x: 0, y: 0 },
withSlider = true,
showGrid = false,
sliderMin = 0.1,
sliderMax = 3,
sliderStep = 0.1,
restrictPosition = false,
}: ImageCropProps) => {
const [crop, setCrop] = useState<Point>(initialCrop)
const [zoom, setZoom] = useState(1)
const handleCropComplete = useCallback(
(_, croppedAreaPixels: Area) => onCropComplete(croppedAreaPixels),
[onCropComplete],
)
const handleZoom = useCallback((zoom: number) => setZoom(zoom), [])
return (
<div className={styles.imageCropperContainer}>
<div className={classNames(styles.imageCropper, { [styles.withoutSlider]: !withSlider })}>
<Cropper
image={src}
crop={crop}
minZoom={0.1}
zoom={zoom}
aspect={ratio}
onCropChange={setCrop}
onCropComplete={handleCropComplete}
onZoomChange={handleZoom}
showGrid={showGrid}
restrictPosition={restrictPosition}
/>
</div>
{withSlider && (
<SliderInput
appearance="compact"
value={zoom}
min={sliderMin}
max={sliderMax}
step={sliderStep}
onChange={handleZoom}
/>
)}
</div>
)
}
If the crop has a minZoom of 0.1 and I crop the image or crop a png, in all cases the transparent background appears black... if anyone has a clue... thanks!