0

EDIT: This is how I managed to make it work. I realized I had to create the image object inside the initial useEffect hook to prevent it from being reloaded at every re-render, and refer to it later using a ref object. Also, I had to import the image src at the start of the code because if I tried to do it like this: image src = "./images/image.png" later when i created the image object, something called Webpack messed up the path and that's why the image wouldn't draw. I'm not clear on the latter part yet, but at least I got it the code work.

import React, { useRef, useEffect, useState } from "react";
import image1 from "./images/image.png";

function MyCanvasComponent() {
  const canvasRef = useRef(null);
  const imageRef = useRef(null);
  const [imageloaded, setImageloaded] = useState(false);

  useEffect(() => {
    imageRef.current = new Image();
    imageRef.current.onload = () => setImageloaded(true);
    imageRef.current.src = image1;
  }, []);

  function draw(image, x) {
    if (canvasRef.current) {
      const canvas = canvasRef.current;
      const context = canvasRef.current.getContext("2d");
      context.clearRect(0, 0, canvas.width, canvas.height);
      context.drawImage(image, x, 0, image.width, image.height);
    }
  }

  let counter = 1;
  setInterval(() => {
    if (imageloaded) {
      if (counter % 2 === 0) {
        draw(imageRef.current, 200);
      } else draw(imageRef.current, 100);
      counter++;
    }
  }, 1000);
  
  return (
    <div>
      <canvas ref={canvasRef} width={300} height={200} />
    </div>
  );
}

function App() {
  return (
    <div>
      <h1>My Canvas App</h1>
      <MyCanvasComponent />
    </div>
  );
}

export default App;

ORIGINAL POST: Using setInterval, I want to show an image moving around on my canvas, which is inside a React component. However, the only way I get the image to display without any errors is when I define the image object inside the very function that draws the image. That way, however, it reloads at every interval, which makes the animation very choppy. When I try to define the image object outside that function, it either doesn't show or gives an error:

Uncaught DOMException: Failed to execute 'drawImage' on 'CanvasRenderingContext2D': The HTMLImageElement provided is in the 'broken' state.

What am I doing wrong?

this way, it works, but it reloads the image at every interval

function draw() {
  const canvas = canvasRef.current;
  const context = canvasRef.current.getContext("2d");
  const image = new Image();
  image.onload = () => {
    context.drawImage(image, x, y, laius, korgus);
  };
  image.src = imageSource;
}

this way (or along these lines, I've tried many ways), I get errors, or nothing displays

function draw() {
  const canvas = canvasRef.current;
  const context = canvasRef.current.getContext("2d");
  context.drawImage(image, x, y, laius, korgus);
}
const image = new Image();
image.onload = () => {
  draw();
};
image.src = imageSource;

when I run this, it tells me that it is an HTML image alright

function isImage(i) {
        return i instanceof HTMLImageElement;
      }
6
  • 1
    Can you show your react code? You only show normal functions and canvasRef. How do you set it? You need to show more context. Best if you have an example that fully reproduces the issue you have. So others can run and debug the code. Commented Nov 25, 2023 at 16:42
  • Forgive the n00b question, but which parts of the code should I show, because it won't let me post my entire code here. Commented Nov 25, 2023 at 16:58
  • You need to create a minimal example that can reproduce the issue. Something you can run. You need to make an effort to reproduce the issue. Start a new project and put part of the code until you will have the same error. Commented Nov 25, 2023 at 17:15
  • Okay, I figured it out myself. I edited the original post with the working code. Maybe it'll be off use to somebody. Commented Nov 26, 2023 at 12:51
  • This is a Q&A website if you have the answer don't edit the question only add it as an answer. Commented Nov 26, 2023 at 15:10

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.