首页 > 解决方案 > 如何创建可以修改其原始函数调用的对象

问题描述

我正在尝试创建一个按钮对象,它可以运行一个类函数(在本例中为 show()),它将改变按钮的颜色。问题是我只能通过每次颜色变化时重复调用 show() 来做到这一点。结果是在屏幕上绘制了大量按钮,但我只想绘制一次按钮。有没有解决的办法?(注意:我让按钮 x 位置增加以显示正在创建的按钮)

let canvas = document.getElementById("JScanvas"),
  c = canvas.getContext("2d");

let mousePosition = {
  x: 0,
  y: 0
};
// ignore, a few functions I might need for this to run

function buildRect(fillColor, outlineColor, outlineSize, x, y, w, h) {
  if (fillColor && outlineColor) {
    c.beginPath();
    c.rect(x, y, w, h);
    c.fillStyle = fillColor;
    c.fill();
    c.lineWidth = outlineSize;
    c.strokeStyle = outlineColor;
    c.stroke();
  } else if (fillColor && !outlineColor) {
    c.beginPath();
    c.rect(x, y, w, h);
    c.fillStyle = fillColor;
    c.fill();
  } else if (!fillColor && outlineColor) {
    c.beginPath();
    c.rect(x, y, w, h);
    c.lineWidth = outlineSize;
    c.strokeStyle = outlineColor;
    c.stroke();
  }
}

function write(str, x, y, color, txtSize, font) {
  let size = txtSize.toString();
  c.font = size + "px" + " " + font;
  c.fillStyle = color;
  c.fillText(str, x, y);
}
// end of useless functions

class button {
  // mouse is {canvs: canvas, mClicked: t/f, mPosition: mousePosition{x, y}}
  constructor(name, order, btnColor, x, y, w, h, txtColor, txtSize, m, f) {
    this.name = name;
    this.order = order;
    this.btnColor = btnColor;
    this.x = x;
    this.y = y;
    this.w = w;
    this.h = h;
    this.txtColor = txtColor;
    this.txtSize = txtSize;
    this.m = m;
    this.f = f;

    //change color when mouse over button
    this.m.canvs.addEventListener("mousemove", (event) => {
      console.log("hello there");

      if (this.x < this.m.mPosition.x && this.m.mPosition.x < this.x + this.w && this.y < this.m.mPosition.y && this.m.mPosition.y < this.y + this.h) {

        if (this.btnColor[0] != "grey") {
          this.btnColor[0] = "grey";
          this.x += 50;
          this.show();
        } else {
          this.btnColor[0] = "red";
          this.x += 50;
          this.show();
        }
      }
    });
  }

  show() {
    if (!this.btnColor[0] && !this.btnColor[0]) {
      buildRect("transparent", false, 1, this.x, this.y, this.w, this.h);
    } else if (!this.btnColor[0]) {
      buildRect(false, this.btnColor[1], 1, this.x, this.y, this.w, this.h);
    } else if (!this.btnColor[1]) {
      buildRect(this.btnColor[0], false, 1, this.x, this.y, this.w, this.h);
    } else {
      buildRect(this.btnColor[0], this.btnColor[1], 1, this.x, this.y, this.w, this.h);
    }
    c.fillStyle = this.txtColor;
    let theString = String(this.txtSize) + "px Arial";
    c.font = theString;
    let width = Math.round(c.measureText(c.fillText(this.name, -1000, 0)).width);

    if (width > this.w) {
      let center = this.x + (this.w / 2);
      let newSize = this.w / width;
      c.font = String(this.txtSize * newSize);
      let newWidth = Math.round(newSize * width);
      c.textAlign = "center";
      c.textBaseline = "middle";
      c.fillText(this.name, this.x + (this.w / 2), this.y + (this.h / 2));

    } else {
      c.textAlign = "center";
      c.textBaseline = "middle";
      c.fillText(this.name, this.x + (this.w / 2), this.y + (this.h / 2));
    }
  }

  clickButton(mouseX, mouseY) {
    if (mouseX >= this.x && mouseX <= this.x + this.w && mouseY >= this.y && mouseY <= this.y + this.h) {
      return true;
    } else {
      return false;
    }
  }

  runf() {
    this.f();
  }
}

//getting mouse position 

function getMousePos(canvas, evt) {
  const rect = canvas.getBoundingClientRect();
  return {
    x: evt.clientX - rect.left,
    y: evt.clientY - rect.top
  };
}

canvas.addEventListener("mousemove", (evt) => {
  let r = getMousePos(canvas, event);
  mousePosition.x = r.x, mousePosition.y = r.y;
});

let mouse = {
  canvs: canvas,
  mClicked: false,
  mPosition: mousePosition
};

//button object to call: ("red" is the color of the button I am trying to change to grey)
let cookie = new button("cookie", 1, ["red", false], 50, 100, 150, 50, "black", 30, mouse, 2);
cookie.show();
<!DOCTYPE html>

<html>

<head>
  <title>Playground</title>

</head>

<body>

  <canvas width="1500" height="1500" id="JScanvas"></canvas>
</body>

</html>

标签: javascriptbuttoncanvas

解决方案


我认为您的代码过于复杂...

这是一个简单的例子,当鼠标在矩形上时我们改变颜色

let canvas = document.getElementById("canvas")
let c = canvas.getContext("2d");

class button {
  constructor(color, x, y, w, h) {
    this.color = color;
    this.x = x;
    this.y = y;
    this.w = w;
    this.h = h;
  }

  draw(mouse) {
    c.beginPath();
    c.rect(this.x, this.y, this.w, this.h);
    if (mouse.x >= this.x && mouse.x <= this.x + this.w &&
      mouse.y >= this.y && mouse.y <= this.y + this.h) {
      c.fillStyle = "gray";
    } else {
      c.fillStyle = this.color;
    }
    c.fill();
  }
}

function getMousePos(evt) {
  if (!evt) return { x: 0, y: 0 }
  const rect = canvas.getBoundingClientRect();
  return { x: evt.clientX - rect.left, y: evt.clientY - rect.top };
}

let buttons = []
buttons.push(new button("red", 50, 100, 40, 20))
buttons.push(new button("blue", 100, 50, 40, 20))

canvas.addEventListener("mousemove", mainDraw);

function mainDraw(evt) {
  let mouse = getMousePos(evt)
  c.clearRect(0, 0, canvas.width, canvas.height);
  buttons.forEach((btn) => {
    btn.draw(mouse)
  })
}

mainDraw()
<canvas id="canvas" width="150" height="150"></canvas>

如您所见,只有一个 addEventListener 并且它位于类按钮之外,逻辑很简单,我们清理整个画布并在每个事件上绘制所有内容......这就是游戏的做法,我相信它会起作用你也在做什么。


推荐阅读