如何创建一个可以修改其原始函数调用的对象



我试图创建一个按钮对象,可以运行类函数(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>

我觉得你的代码太复杂了…

下面是一个简单的例子,当鼠标放在矩形

上时,我们改变颜色

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,它在类按钮之外,逻辑很简单,我们清理整个画布并绘制每个事件上的所有内容…游戏就是这样做的,我相信这对你的工作也会起作用。

最新更新