简体   繁体   中英

How to create an object that can modify its original function call

I am trying to create a button object which can run a class function (show() in this case) that will change the button's color. The problem is I can only do this by calling show() repeatedly each time the color changes. The result is a ton of buttons being drawn on the screen, but I would like to only draw the button once. Is there a way around this? (Note: I have the button x position increasing to show the buttons being created)

 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 = rx, mousePosition.y = ry; }); 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>

I think you have over complicated your code...

Here is a simple example where we change the color when the mouse is over the rectangle

 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>

As you can see there is only one addEventListener and it is outside the class button, the logic is simple, we clean the entire canvas and draw everything on every event... that is how games do it, I'm sure that will work for what you are doing too.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM