JavaScript 调整大小 Window 更改边界

JavaScript Resizing Window Changes Boundaries

我不确定如何正确地给这个问题起标题。

基本上,当我的屏幕 canvas 应该是这样的:

然而,当我稍微调整 window 的大小时,它会变成这样:

一切似乎都被奇怪地拉伸了。

由于我是 JS 的新手,所以我不确定有什么特别有用的。这是我的“Globals”class,我在其中保存 canvas 信息:

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);
    }
}

如果有任何其他帮助,请告诉我。

编辑:

这是我遇到的一个错误:

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)

不过,我认为应该定义this.canvas.width,因为定义了this.canvas。

问题是调整大小处理函数中 this 的值。

$(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;
});

调整大小处理函数内部的 thisGlobals class 的构造函数中函数外部的 this 不同。调整大小处理函数中的 this 实际上不是指 Globals 对象,而是指 Window 对象。

// 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

代码中的 Window 对象没有 canvas 属性,因此当您在调整大小函数中调用 this.canvas 时,它将计算为 undefined(因此错误)。

一个简单的解决方案是在调整大小处理函数中使用箭头函数。

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;
});

或者您可以创建对 Globals 实例的引用,调整大小处理函数可以访问该实例:

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();