tarte_au_citron
tarte_au_citron

Reputation: 1

Why does pasting an image into an SVG canvas only works if there are other elements present (like an SVG circle) in my webapp?

I am working on a map creation project in React. It consists of a 'canvas', which is an svg element. On that canvas, you can add nodes, which are SVG circles, edges, which as SVG lines and finally you can paste images.

**Problem: **

When I go on the page for the first time or I reload the page, if I try to paste the image doing Ctrl + V, handlePaste isn't called and nothing appears on the canvas. If I add a node then I paste the image, handlePaste is called and the image is pasted. If I delete the node, the same problem persists. This problem only happens on Chrome / Chromium Browser. I don't have this problem on Firefox.

**What I have tried: **

None of the solutions above fixed my problem.

Also about handlePaste being called, i put a console.log inside the handlePaste function, when there are no nodes it was never called.

Here's a sample of my code:

const Canvas = () => {

  const canvasRef = useRef<SVGSVGElement>(null);
  const [image, setImage] = useState<string | null>(null);

  const handlePaste = (event: React.ClipboardEvent<SVGSVGElement>) => {
    console.log("Ctrl + V used")
    const clipboardData = event.clipboardData;
    if (mode !== 'edit' || !clipboardData) {
      console.log("Item cannot be pasted")
      return;
    }

    let items = clipboardData.items;
    if (items) {
      for (const item of items) {
        if (item.type.includes('image')) {
          const file = item.getAsFile();
          if (file) {
            const reader = new FileReader();
            reader.onloadend = (e: ProgressEvent<FileReader>) => {
              const imageData = e.target?.result;
              if (typeof imageData === 'string') {
                const img = new Image();
                img.onload = () => {
                  setImage(imageData); 
                  const newImage = insertImage(graphHandler, imageData, img.width, img.height);
                  setSelectedEntity({ kind: 'image', imgId: newImage.id });
                };
                img.src = imageData;
              }
            };
            reader.readAsDataURL(file);
          }
          break;
        }
      }
    }
  }

  useEffect(() => {
    if (canvasRef.current) {
      canvasRef.current.focus();
    }
  }, []); 

  useEffect(() => {
    const handlePaste = (event: ClipboardEvent) => {
      const items = event.clipboardData?.items;
      console.log(items);
    };

    const canvasElem = canvasRef.current;
    canvasElem?.addEventListener('paste', handlePaste);

    canvasElem?.focus();

    return () => {
      canvasElem?.removeEventListener('paste', handlePaste);
    };
  }, []);

return (
    <div>
      <div>
        <CanvasContext.Provider value={{ ref: canvasRef, action, setAction }}> {/* Just a context */}
          <svg
            ref={canvasRef}
            id="canvas"
            width="1000"
            height="1000"
            tabIndex={0}
            viewBox="0 0 1000 1000"
            fill="white"
            xmlns="http://www.w3.org/2000/svg"
            onClick={handleClick}
            onPaste={handlePaste}
          >
            <g>
              {/*images go here*/}
              <g>
                {/*nodes and edges go here*/}
              </g>
            </g> 
          </svg>
        </CanvasContext.Provider>
      </div>
    </div>
  );
};

export default Canvas;

Upvotes: 0

Views: 32

Answers (0)

Related Questions