React P5 loading image question. How do I pass prop values to preload image?

I am relatively new to P5 and I just don’t quite understand how to load an image using react p5-wrapper and the prop values together. I’m gettting an error that my img variable is not being read and is undefined. The only alternative solution I have seen is @atoro but it doesn’t quite do dynamic image loading as I am trying to do.


**Sketch Function**

export default function sketch (p) {
  let rotation = 0;
  let img;
  const imgs = []
  p.setup = function () {
    p.createCanvas(600, 400, p.WEBGL);

  };

  p.myCustomRedrawAccordingToNewPropsHandler = function (props) {
    if (props.rotation){
      rotation = props.rotation * Math.PI / 180;
      console.log(rotation)
    }
    if(props.img){
      img = props.img
      console.log(img)
      p.loadImage(img)
    }

  };

  p.draw = function () {

    p.image(img, 10, 10, 50, 50)

    // p.image(img);
    p.background(100);
    p.normalMaterial();
    p.noStroke();
    p.push();
    p.rotateY(rotation);
    p.box(100);
    p.pop();
  };
};

Hi! I recently made progress on something similar using the p5 react wrapper. I’m wondering what it looks like when you are calling the P5Wrapper component, are you passing in the img like this? <P5Wrapper sketch={sketch} img={img} />

I’m wondering if maybe you just have to move the p.loadImage(img) line into a p.preload function, i think your img variable should be available there. I think what happens in myCustomRedrawAccordingToNewPropsHandler is only meant to set variables, not do any actual p5 stuff. Hope that helps.

Yes I tried to set it up similar exactly like that. Unfortunately I can’t insert p.loadImage(img) because then img would be undefined cause it should be a dynamic prop value.

Sorry about that! Hmm. I have one more idea - from what you said, it sounds like maybe there could be an if statement added into p.preload, so that loadImage is only called if img has been passed in from the props handler and defined.

@eagle3y3z It is absolutely possible for you to use some of the approaches described in my posts.

Anyway, let’s look on your example:

  1. What is the type of props.img? I suppose it is a string containing a path/URL to the image?
  2. If that’s the case, your code should be something like this:
let myImageURL = ''
let myImage = null

p.myCustomRedrawAccordingToNewPropsHandler = function (props) {
    if (props.img) {
        myImageURL = props.img
    }
    // else {
    //     myImageURL = ''
    // }
}

p.draw = function() {
    if (myImageURL) {
        myImage = p.loadImage(myImageURL, (img) => myImage = img)
        myImageURL = ''
    }
    // else {
    //     myImage = null
    // }

    if (myImage) {
        p.image(myImage, 10, 10, 50, 50)
    }
}

(The code bellow is one of many possible approaches)

Keep in mind what p5 documentation says:
“loadImage() - Loads an image from a path and creates a p5.Image from it. The image may not be immediately available for rendering. If you want to ensure that the image is ready before doing anything with it, place the loadImage() call in preload(). You may also supply a callback function to handle the image when it’s ready.”

The important part is: “The image may not be immediately available for rendering.” Loading a image is an asynchronous task, use preload(), or callback function or wrap loadImage() in a JS Promise.

I hope the explanations above will be helpful to you. Good luck!

3 Likes