react-image-crop icon indicating copy to clipboard operation
react-image-crop copied to clipboard

No image inside of canvas preview

Open christopher-ha opened this issue 3 years ago • 1 comments

I'm trying to follow the demo but I'm struggling to figure out where the image actually gets rendered in the canvas, and I think I'm missing something.

image

Here is my code:

export default function Looks() {
  const [image, setImage] = useState(null);
  const imgRef = useRef();
  const previewCanvasRef = useRef();
  const [crop, setCrop] = useState();
  const [croppedImageUrl, setCroppedImageUrl] = useState();
  const [aspect, setAspect] = useState(0);

  const onSelectFile = (event) => {
    if (event.target.files && event.target.files.length > 0) {
      const reader = new FileReader();
      reader.addEventListener("load", () => setImage(reader.result));
      reader.readAsDataURL(event.target.files[0]);
    }
  };

  function onImageLoad(event) {
    if (aspect) {
      const { width, height } = event.currentTarget;
      setCrop(centerAspectCrop(width, height, aspect));
    }
  }

  function imageCropComplete(crop) {
    makeClientCrop(crop);
  }

  const makeClientCrop = async (crop) => {
    if ((image, crop.width && crop.height)) {
      const croppedImg = await getCroppedImg(
        imgRef.current,
        crop,
        "newFile.jpeg"
      );
      setCroppedImageUrl(croppedImg);
    }
  };
  console.log(croppedImageUrl);

  const handleSubmit = () => {
    // convert blob to File
    // upload
  };

  const getCroppedImg = (sourceImage, crop, fileName) => {
    const canvas = document.createElement("canvas");
    const scaleX = sourceImage.naturalWidth / sourceImage.width;
    const scaleY = sourceImage.naturalHeight / sourceImage.height;
    canvas.width = crop.width;
    canvas.height = crop.height;
    const ctx = canvas.getContext("2d");
    ctx.drawImage(
      sourceImage,
      crop.x * scaleX,
      crop.y * scaleY,
      crop.width * scaleX,
      crop.height * scaleY,
      0,
      0,
      crop.width,
      crop.height
    );

    try {
      return new Promise((resolve) => {
        canvas.toBlob((file) => {
          resolve(URL.createObjectURL(file));
        }, "image/jpeg");
      });
    } catch (error) {
      console.log(error);
      return null;
    }
  };

  return (
    <main>
      <Head>
        <title>Looks Builder</title>
      </Head>
      <Header title={"Looks Builder"} />
      <div>
        <input type="file" accept="image/*" onChange={onSelectFile} />
        <ReactCrop
          crop={crop}
          onChange={(c) => setCrop(c)}
          onComplete={imageCropComplete}
        >
          <img src={image} onLoad={onImageLoad} ref={imgRef} />
        </ReactCrop>
      </div>
      <div>
        {Boolean(crop) && (
          <canvas
            ref={previewCanvasRef}
            style={{
              border: "1px solid black",
              objectFit: "contain",
              width: crop.width,
              height: crop.height,
            }}
          />
        )}
      </div>
    </main>
  );
}

christopher-ha avatar Jul 27 '22 01:07 christopher-ha

Hi, are you able to make a working Codesandbox?

When you say demo, which are you following? You can see a working example over here: https://codesandbox.io/s/react-image-crop-demo-with-react-hooks-y831o

dominictobias avatar Sep 08 '22 21:09 dominictobias