1

I am not sure how to correctly title this issue.

Basically, when my when my the screen is canvas is supposed to look like this:

enter image description here

However, when I resize the window even slightly, it turns into this:

enter image description here

Everything seems to be stretched weirdly.

As I am new to JS, I am not sure what particularly would be helpful. Here is my "Globals" class, where I hold canvas information:

class Globals{
    constructor(){
        this.canvas = document.getElementById('game__canvas');
        this.ctx = this.canvas.getContext('2d');
        this.bg = new Image();
        this.bg.src = "https://art.pixilart.com/61f484ce7cee5ad.png";
        this.win_h = $(window).height();
        this.win_w = $(window).width();
        this.canvas_rect = this.canvas.getBoundingClientRect();
        this.MAX_BERRIES = 100;

        // set dims of canvas
        $(window).resize(function(){
            this.win_w = window.innerWidth;
            this.win_h = window.innerHeight;
            
            this.canvas.width = this.win_w;
            this.canvas.height = this.win_h;
        });

        this.canvas.width = this.win_w;
        this.canvas.height = this.win_h;
    }
    clearListeners(){
        // removes all event listeners
        var cleared = this.canvas.cloneNode(true);
        this.canvas.parentNode.replaceChild(cleared,this.canvas);
    }
}

Please let me know if there is anything other things that would help.

Edit:

Here is an error I am getting:

main.js:35 Uncaught TypeError: Cannot set property 'width' of undefined
    at main.js:35
    at dispatch (jquery.min.js:2)
    at v.handle (jquery.min.js:2)

However, I thought that this.canvas.width should be defined, as this.canvas is defined.

Steak
  • 514
  • 3
  • 15
  • While @Bas van der Linden 's comment fixed the scope issue, my actual problem with resizing can be fixed from this post: https://stackoverflow.com/questions/17854336/html-blurry-canvas-images/17854337#17854337 – Steak May 20 '21 at 15:44

1 Answers1

2

The problem is the value of this inside your resize handler function.

$(window).resize(function () {
  this.win_w = window.innerWidth;
  this.win_h = window.innerHeight;

  this.canvas.width = this.win_w;
  this.canvas.height = this.win_h;
});

The this inside the resize handler function is not the same as the this outside the function in the constructor of the Globals class. The this in the resize handler function actually doesn't refer to the Globals object, but to the Window object.

// console.log(this) inside `Globals` constructor
Globals {globals: Globals, canvas: canvas#game__canvas, ctx: CanvasRenderingContext2D, bg: img, win_h: 669, …}

// console.log(this) inside resize handler function
Window {window: Window, self: Window, document: document, name: "", location: Location, …}

Inside a function, the value of this depends on how the function is called. Since the following code is not in strict mode, and because the value of this is not set by the call, this will default to the global object, which is window in a browser.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this#function_context

The Window object in your code doesn't have a canvas property, so when you call this.canvas inside the resize function it will evaluate to undefined (hence the error).

An easy solution could be to use an arrow function in your resize handler function.

Arrow functions are designed to allow methods to execute within different scopes, because Arrow functions establish "this" based on the scope the Arrow function is defined within.

Another mdn quote (slightly rephrased)

$(window).resize(() => {
  this.win_w = window.innerWidth;
  this.win_h = window.innerHeight;

  this.canvas.width = this.win_w;
  this.canvas.height = this.win_h;
});

Or you could create a reference to the Globals instance which the resize handler function has access to:

class Globals {
  globals = this; // public field declaration
  constructor() {
    this.canvas = document.getElementById("game__canvas");
    this.ctx = this.canvas.getContext("2d");
    this.bg = new Image();
    this.bg.src = "https://art.pixilart.com/61f484ce7cee5ad.png";
    this.win_h = $(window).height();
    this.win_w = $(window).width();
    this.canvas_rect = this.canvas.getBoundingClientRect();
    this.MAX_BERRIES = 100;

    // set dims of canvas
    $(window).resize(function () {
      globals.canvas.width = window.innerWidth;
      globals.canvas.height = window.innerHeight;
    });

    this.canvas.width = this.win_w;
    this.canvas.height = this.win_h;
  }
  clearListeners() {
    // removes all event listeners
    var cleared = this.canvas.cloneNode(true);
    this.canvas.parentNode.replaceChild(cleared, this.canvas);
  }
}
const globals = new Globals();
5eb
  • 14,798
  • 5
  • 21
  • 65