Search code examples
javascriptreactjstypescriptcanvas

Add image on top of canvas on a certain position


So I am trying to rebuild this site

I am using React (same as the given site) and the same cropper tool they are using. I use react-image-crop for cropping

There is a lot of code so I just added the things that need to be added

This is my code so far

The JSX

<canvas
  ref={canvasRef}
  width={1800}
  height={1800}
  style={{
    backgroundImage: 'url("https://bizexpo.localvocalbusiness.com:8443/images/stallimage/1672025924668.jpg")',
    backgroundSize: "cover",
    backgroundRepeat: "no-repeat",
    backgroundPosition: "center center",
    width: "100%",
    height: "100%",
  }}
/>

The JS logic

async function onImageUpload(files) {
  setOpen(true);
  const [file] = files;
  const url = URL.createObjectURL(file);
  setImageUrl(url);
  const ctx = canvasRef.current?.getContext("2d");
  const canvas = canvasRef.current;
  const image = new Image();
  image.src = url;
  image.onload = () => {
    // I have no idea what to do here 😑
  };
}

I tried many ways to replicate the same thing they do, by drawing the image on the canvas. Spent a whole night on this. Read many articles, and saw many videos but I am unable to do the same in my version.

Can someone please help me with this?


Solution

  • You need to know co-ordinates of that circle in the background where selected image will be placed. Try using the following:

    function App() {
      const canvasRef = useRef(null);
      const contextRef = useRef(null);
    
      useEffect(() => {
        const canvas = canvasRef.current;
        contextRef.current = canvas.getContext("2d");
      }, [canvasRef]);
    
      // ...
    }
    
    const image = new Image();
    image.src = URL.createObjectURL(file);
    
    image.onload = () => {
      contextRef.current.beginPath();
    
      // Worked fine for size 1800*1800 present in the question
      const radius = 322;
      const marginLeft = 420;
      const marginTop = 860;
    
      contextRef.current.arc(
        marginLeft,
        marginTop,
        radius,
        0,
        2 * Math.PI
      );
    
      contextRef.current.clip();
    
      contextRef.current.drawImage(
        image,
        marginLeft - radius,
        marginTop - radius,
        radius * 2,
        radius * 2
      );
    };
    

    Checkout MDN for more information about arc() and drawImage().