2

I am trying to crop an image using 'react-image-crop' package and set the output into result variable.

import React, { useState } from 'react'
import ReactCrop  from 'react-image-crop'
import 'react-image-crop/dist/ReactCrop.css'



export const Imagecrop = () => {
    
    const [src, setSrc] = useState(null)
    const handleFileChange = e =>{
        console.log(e.target.files[0])
        setSrc(URL.createObjectURL(e.target.files[0]))
        console.log("src", src)
    }
    const [image, setImage] = useState(null)
    const [crop, setCrop] = useState()
    const [result, setResult] = useState(null);    

    const cropImageNow = () => {
        console.log("image.naturalWidth", image?.naturalWidth)
        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');
      
        const pixelRatio = window.devicePixelRatio;
        canvas.width = crop.width * pixelRatio;
        canvas.height = crop.height * pixelRatio;
        ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
        ctx.imageSmoothingQuality = 'high';
      
        ctx.drawImage(
          image,
          crop.x * scaleX,
          crop.y * scaleY,
          crop.width * scaleX,
          crop.height * scaleY,
          0,
          0,
          crop.width,
          crop.height,
        );
          
        const base64Image = canvas.toDataURL('image/jpeg');
        setResult(base64Image);
      };

    return (
        <div className='container'>
            <div className='row'>
                <div className='col-6'>
                    <input type='file' accept='image/*' onChange={handleFileChange} />
                </div>
                <div className='col-6'>
                {src && (
                    <ReactCrop crop={crop} aspect={800 / 200} onChange={setCrop}>
                        <img src={src} />
                    </ReactCrop>
                    
                )}
                {src && <button onClick={cropImageNow}>Crop</button>}
                
                </div>
            
            </div>
        </div>
    )
}


But there is an error "TypeError: Failed to execute 'drawImage' on 'CanvasRenderingContext2D': The provided value is not of type '(CSSImageValue or HTMLCanvasElement or HTMLImageElement or HTMLVideoElement or ImageBitmap or OffscreenCanvas or SVGImageElement or VideoFrame)'."

enter image description here

Please give me a solution to fix this problem.

Drew Reese
  • 165,259
  • 14
  • 153
  • 181
user15361826
  • 322
  • 2
  • 13

1 Answers1

0

I just faced the same issue. In my cause the problem was that the image I was using in method cropImageNow was the image file and it needs to be the image ref:

import React, { useState } from 'react';
import ReactCrop  from 'react-image-crop';
import 'react-image-crop/dist/ReactCrop.css';


export const Imagecrop = () => {
    
    const [src, setSrc] = useState(null)
    const handleFileChange = e =>{
        console.log(e.target.files[0])
        setSrc(URL.createObjectURL(e.target.files[0]))
        console.log("src", src)
    }
    const [image, setImage] = useState(null)
    const [imageRef, setImageRef] = useState(null)
    const [crop, setCrop] = useState()
    const [result, setResult] = useState(null);    

    const cropImageNow = () => {
        console.log("image.naturalWidth", image?.naturalWidth)
        const canvas = document.createElement('canvas');
        const scaleX = imageRef?.naturalWidth / imageRef?.width;
        const scaleY = imageRef?.naturalHeight / imageRef?.height;
        canvas.width = crop.width;
        canvas.height = crop.height;
        const ctx = canvas.getContext('2d');
      
        const pixelRatio = window.devicePixelRatio;
        canvas.width = crop.width * pixelRatio;
        canvas.height = crop.height * pixelRatio;
        ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
        ctx.imageSmoothingQuality = 'high';
      
        ctx.drawImage(
          imageRef,
          crop.x * scaleX,
          crop.y * scaleY,
          crop.width * scaleX,
          crop.height * scaleY,
          0,
          0,
          crop.width,
          crop.height,
        );
          
        const base64Image = canvas.toDataURL('image/jpeg');
        setResult(base64Image);
      };

    return (
        <div className='container'>
            <div className='row'>
                <div className='col-6'>
                    <input type='file' accept='image/*' onChange={handleFileChange} />
                </div>
                <div className='col-6'>
                {src && (
                    <ReactCrop crop={crop} aspect={800 / 200} onChange={setCrop}>
                        <img src={src} 
                          onLoad={(e: any) => {
                           setImageRef(e.target);
                          }}/>
                    </ReactCrop>
                    
                )}
                {src && <button onClick={cropImageNow}>Crop</button>}
                
                </div>
            
            </div>
        </div>
    )
}