javascript - 如何创建可以修改其原始函数调用的对象
问题描述
我正在尝试创建一个按钮对象,它可以运行一个类函数(在本例中为 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 并且它位于类按钮之外,逻辑很简单,我们清理整个画布并在每个事件上绘制所有内容......这就是游戏的做法,我相信它会起作用你也在做什么。
推荐阅读
- java - 无法使用 .sh 文件运行我的 .jar 文件
- javascript - 显示来自 Codeigniter 函数的 JSON html 数据
- javascript - 为什么 Chrome 网上应用店在发布 chrome 扩展时会抛出错误
- image - 加载 PNG 图像文件以作为 Image 对象在 Vaadin Flow 布局上显示
- ruby-on-rails - Searchkick `all` 用于带有 OR 的多个数组
- java - JLabel 最初不显示
- php - 使用 AJAX 和 PHP 收集复选框值的问题
- postgresql - PostgreSQL 错误:错误:插入的目标列多于表达式
- ios - Circle Fill At 80 %
- powershell - Changing date for file Auditing script