点击eventListner会调用我的函数,但前提是我将其传递给匿名函数

时间:2019-01-11 04:46:54

标签: javascript canvas

我有一个单击eventListener,正在调用静态方法“ clearCanv”,但是 不会调用“ clearCanv”内部的一种方法

  

this.ctx.clearRect(x,y,this.canv.width,this.canv.width)

正在调用“ clearCanv”,但未调用该方法。

但是,如果我将clickevenetListner传递给一个匿名函数,并且突然从匿名函数内部调用我的静态方法“ clearCanv”。

有人可以解释为什么会这样吗?

问题出在JS的最后几行。 我正在使用Firefox

class Board {
  static initalize() {
    // Create Canvas
    this.canv = document.createElement("canvas");
    this.ctx = this.canv.getContext("2d");

    this.canv.height = window.innerHeight;
    this.canv.width = window.innerWidth;
    document.body.appendChild(this.canv);

    this.prevX, this.prevY;
    this.lineWidth = 25;
    this.color = "white"; //Default color
    this.prevColor = this.color;
    this.erase = false;
    // Bindings
    this.draw = Board.draw.bind(this);
    this.clearCanv = Board.clearCanv.bind(this);
  }


  static draw({
    x,
    y
  }) {
    // Draw a cericle on X, Y
    this.ctx.beginPath();
    this.ctx.fillStyle = this.color;
    this.ctx.arc(x, y, this.lineWidth / 2, 0, Math.PI * 2);
    this.ctx.fill();
    this.ctx.closePath();

    // If we have prevX/Y draw a line from prevX/Y
    // To currentX/Y
    if (this.prevX && this.prevY) {
      this.ctx.beginPath();
      this.ctx.moveTo(this.prevX, this.prevY);
      this.ctx.strokeStyle = this.color;
      this.ctx.lineTo(x, y);
      this.ctx.lineWidth = this.lineWidth;
      this.ctx.stroke();
      this.ctx.closePath();
    }
    // Recored X/Y
    this.prevX = x;
    this.prevY = y;
  }
  static clearCanv(x = 0, y = 0) {
    this.ctx.clearRect(x, y, this.canv.width, this.canv.height);
  }
}

Board.initalize();

Board.canv.addEventListener("mousedown", function() {
  this.addEventListener("mousemove", Board.draw);
});

Board.canv.addEventListener("mouseup", function() {
  Board.prevX = null;
  Board.prevY = null;
  Board.canv.removeEventListener("mousemove", Board.draw);
});


const clearBtn = document.getElementById("clear");
//This does not work
clearBtn.addEventListener("click", Board.clearCanv);

// This works for some reson
//clearBtn.addEventListener("click", function(){
//  Board.clearCanv();
//});
html,
body {
  height: 100%;
  width: 100%;
  padding: 0;
  margin: 0;
  overflow: hidden;
  position: relative;
}

canvas {
  height: 100%;
  width: 100%;
  background: black;
}

#clear {
  position: absolute;
  /* z-index: 222; */
}

#erase {
  position: absolute;
  left: 5.5rem;
}

.erase-selected {
  position: absolute;
  left: 5.5rem;
  opacity: 0.7;
}

#mouseColor {
  position: absolute;
  left: 11.2rem;
}

.font-size-select {
  position: absolute;
  left: 15.5rem;
}

.bg-color {
  position: absolute;
  left: 19.5rem;
}
<button id="clear">Clear</button><button id="erase">erase</button><input type="color" id="mouseColor" />
<select class="font-size-select" id="select-size">
  <option selected value="10">10</option>
  <option value="15">15</option>
  <option value="20">20</option>
  <option value="25">25</option>
</select>
<select class="bg-color" id="select-bg">
  <option selected value="black">Dark</option>
  <option value="white">Light</option>
</select>

1 个答案:

答案 0 :(得分:2)

您在这里面临的问题是x=0, y=0方法的clearCanv参数被事件侦听器传递的参数(即x= Event)覆盖。
clearRect()会静默忽略该呼叫,因为xNaN所涉及的内容。

只需在此处删除参数即可解决此问题,因为我想您不希望它不是0之外的任何东西。

class Board {
  static initalize() {
    // Create Canvas
    this.canv = document.createElement("canvas");
    this.ctx = this.canv.getContext("2d");

    this.canv.height = window.innerHeight;
    this.canv.width = window.innerWidth;
    document.body.appendChild(this.canv);

    this.prevX, this.prevY;
    this.lineWidth = 25;
    this.color = "white"; //Default color
    this.prevColor = this.color;
    this.erase = false;
    // Bindings
    this.draw = Board.draw.bind(this);
    this.clearCanv = Board.clearCanv.bind(this);
  }


  static draw({
    x,
    y
  }) {
    // Draw a cericle on X, Y
    this.ctx.beginPath();
    this.ctx.fillStyle = this.color;
    this.ctx.arc(x, y, this.lineWidth / 2, 0, Math.PI * 2);
    this.ctx.fill();
    this.ctx.closePath();

    // If we have prevX/Y draw a line from prevX/Y
    // To currentX/Y
    if (this.prevX && this.prevY) {
      this.ctx.beginPath();
      this.ctx.moveTo(this.prevX, this.prevY);
      this.ctx.strokeStyle = this.color;
      this.ctx.lineTo(x, y);
      this.ctx.lineWidth = this.lineWidth;
      this.ctx.stroke();
      this.ctx.closePath();
    }
    // Recored X/Y
    this.prevX = x;
    this.prevY = y;
  }
// here remove the params  
//  static clearCanv(x = 0, y = 0) {
  static clearCanv() {
    this.ctx.clearRect(0, 0, this.canv.width, this.canv.height);
  }
}

Board.initalize();

Board.canv.addEventListener("mousedown", function() {
  this.addEventListener("mousemove", Board.draw);
});

Board.canv.addEventListener("mouseup", function() {
  Board.prevX = null;
  Board.prevY = null;
  Board.canv.removeEventListener("mousemove", Board.draw);
});


const clearBtn = document.getElementById("clear");

clearBtn.addEventListener("click", Board.clearCanv);

// This worked because here the params were not overridden
//clearBtn.addEventListener("click", function(){
//  Board.clearCanv();
//});
html,
body {
  height: 100%;
  width: 100%;
  padding: 0;
  margin: 0;
  overflow: hidden;
  position: relative;
}

canvas {
  height: 100%;
  width: 100%;
  background: black;
}

#clear {
  position: absolute;
  /* z-index: 222; */
}

#erase {
  position: absolute;
  left: 5.5rem;
}

.erase-selected {
  position: absolute;
  left: 5.5rem;
  opacity: 0.7;
}

#mouseColor {
  position: absolute;
  left: 11.2rem;
}

.font-size-select {
  position: absolute;
  left: 15.5rem;
}

.bg-color {
  position: absolute;
  left: 19.5rem;
}
<button id="clear">Clear</button><button id="erase">erase</button><input type="color" id="mouseColor" />
<select class="font-size-select" id="select-size">
  <option selected value="10">10</option>
  <option value="15">15</option>
  <option value="20">20</option>
  <option value="25">25</option>
</select>
<select class="bg-color" id="select-bg">
  <option selected value="black">Dark</option>
  <option value="white">Light</option>
</select>



现在,让您继续走这条路真的很难。您完全滥用这里的语言。

您正在使用这个 class ,就像它是一个实例一样。取而代之的是删除所有这些static,创建一个真实的 class ,然后创建该 class 的新实例。

class Board {
  constructor() {
    // Create Canvas
    this.canv = document.createElement("canvas");
    this.ctx = this.canv.getContext("2d");

    this.canv.height = window.innerHeight;
    this.canv.width = window.innerWidth;
    document.body.appendChild(this.canv);

    this.prevX, this.prevY;
    this.lineWidth = 25;
    this.color = "white"; //Default color
    this.prevColor = this.color;
    this.erase = false;
    // Bindings
    this.draw = this.draw.bind(this);
    this.clearCanv = this.clearCanv.bind(this);

  }


  draw({x,y}) {
    // Draw a circle on X, Y
    this.ctx.beginPath();
    this.ctx.fillStyle = this.color;
    this.ctx.arc(x, y, this.lineWidth / 2, 0, Math.PI * 2);
    this.ctx.fill();
    this.ctx.closePath();

    // If we have prevX/Y draw a line from prevX/Y
    // To currentX/Y
    if (this.prevX && this.prevY) {
      this.ctx.beginPath();
      this.ctx.moveTo(this.prevX, this.prevY);
      this.ctx.strokeStyle = this.color;
      this.ctx.lineTo(x, y);
      this.ctx.lineWidth = this.lineWidth;
      this.ctx.stroke();
      this.ctx.closePath();
    }
    // Recored X/Y
    this.prevX = x;
    this.prevY = y;
  }
  clearCanv() {
    this.ctx.clearRect(0, 0, this.canv.width, this.canv.height);
  }
}

// create an instance of Board
const board = new Board();

board.canv.addEventListener("mousedown", function() {
  this.addEventListener("mousemove", board.draw);
});

board.canv.addEventListener("mouseup", function() {
  board.prevX = null;
  board.prevY = null;
  board.canv.removeEventListener("mousemove", board.draw);
});


const clearBtn = document.getElementById("clear");

clearBtn.addEventListener("click", board.clearCanv);
html,
body {
  height: 100%;
  width: 100%;
  padding: 0;
  margin: 0;
  overflow: hidden;
  position: relative;
}

canvas {
  height: 100%;
  width: 100%;
  background: black;
}

#clear {
  position: absolute;
  /* z-index: 222; */
}

#erase {
  position: absolute;
  left: 5.5rem;
}

.erase-selected {
  position: absolute;
  left: 5.5rem;
  opacity: 0.7;
}

#mouseColor {
  position: absolute;
  left: 11.2rem;
}

.font-size-select {
  position: absolute;
  left: 15.5rem;
}

.bg-color {
  position: absolute;
  left: 19.5rem;
}
<button id="clear">Clear</button><button id="erase">erase</button><input type="color" id="mouseColor" />
<select class="font-size-select" id="select-size">
  <option selected value="10">10</option>
  <option value="15">15</option>
  <option value="20">20</option>
  <option value="25">25</option>
</select>
<select class="bg-color" id="select-bg">
  <option selected value="black">Dark</option>
  <option value="white">Light</option>
</select>