Roguelike Game in React.js/Canvas--Why won't createPattern work?

No idea why createPattern won’t work. Using React; have put img tag at the bottom of the component’s returned JSX. ‘Floor’ is logging ‘null’ to console. Why? P.S. I’ve just put a dummy image in the img tag src at this point, because I was concerned the gif file I’d originally tried might be the problem.
How can I accomplish creating textures from imgs? My idea for my game kinda depends on it. :neutral_face:

drawRooms() {
    //places rooms on top of canvas 2 (lowest layer)
    const ctx2 = this.refs.canvas2.getContext('2d');
    let img = new Image();
    img.src = document.getElementsByClassName('greenery')[0];
    const floor = ctx2.createPattern(img, "repeat");
    console.log(floor);
    ctx2.fillStyle = floor;
    ctx2.fillRect(0, 0, width, height);
    /*ctx2.fillStyle='grey';
    this.state.dungeon.map((room) => {
      ctx2.fillRect(room.x, room.y, room.w, room.h);
    });*/
  }

 render() {
    return (
      <div>
      <div className="center-div">
        {/* PLAYER */}
      <canvas id="c1" ref="canvas1" width={width} height={height} />
        {/* DUNGEON */}
      <canvas id="c2" ref="canvas2" width={width} height={height} />
        {/* SCREEN */}
      <canvas id="c3" ref="canvas3" width={width} height={height} />
        
      </div>
      {/* STATS */}
      <canvas id="c4" ref="canvas4" width={width} height={height} />
      <img className="greenery" ref="greenery" alt="pattern" src="https://gamealchemist.files.wordpress.com/2013/08/varlinerounded.png"/>
      </div>
    );
  }
}

It looks like the floor instance of Image isn’t loaded when you do console.log
You need to wait for the load event. So something like this -

floor.onload = function() {
  console.log( floor );
  ctx2.fillStyle = floor;
.........
};

Uncaught TypeError: Cannot set property 'onload' of null

what does console.log( ctx2 ) give?

CanvasRenderingContext2D {canvas: canvas#c2, globalAlpha: 1, globalCompositeOperation: "source-over", filter: "none", imageSmoothingEnabled: true…}

only thing I can think of is the document.getElementsByClassName('greenery')[0] returning anything?

When is drawRooms being called? Is it from componentDidMount()?

I’m in work now but if you have this on GitHub and share with me I can have a look at it more closely when I get home.

GitHub id is jjmax75

hmm… that’s giving http://localhost:3000/undefined

yes, drawRooms() is being called from componentDidMount().

Have a look at this - https://codepen.io/jjmax/pen/ZyKMQQ

Using querySelector should do it.

I messed that example up though :blush: - vanilla JS and I misspelled class as className.

Send me a link to repo and I’ll have a look later

Still null. Thanks for trying, btw. Appreciate it.

I think the img isn’t rendered yet when getElementsByClassName is called

It should work and there’s a couple of different lifecycle methods in React which might help.

I’ll have a look later if you want but for now I’m out of ideas on this one.

Would it be OK to add the image tag directly rather than rendering and then getting it?

Hi, this works

    const ctx2 = this.refs.canvas2.getContext('2d');
    let img = new Image();
    img.src = "https://gamealchemist.files.wordpress.com/2013/08/varlinerounded.png";
    img.onload = () => {
      const floor = ctx2.createPattern(img, "repeat");
      ctx2.fillStyle = floor;
.......
    }

Can use the img url directly, is there a reason to render it to the canvas?

If so, having looked at your code I think we can get that to work by moving some bits around

Let me know how this goes for you

1 Like

THANK YOU SO MUCH!

:grinning: