Search code examples
javascripthtml5-canvas

Tried to create a class for a button creating, but didn't get it with Canvas Context


I'm creating a game and I started with the menu. I tried to create a object class called button (also tried it with function). I made it with canvas context 2D. It works all fine, but when I run the code, the buttons created doesn't center it with translate. It kind of does when I use it with only one of them, but when I create more it doesn't go for the center. The script below for more context:

class Button{ //maybe change this for a function, try with another html code and see if it works
    // Define the button properties that we will call to create a especified one.
    constructor(color, textColor, name, x, y, width, height, fontSize){
        
        const textWidth = context.measureText(name).width //Define a especial variable of the text width that will debug in console.log
        
        // Define all button properties in constructor.
        this.color = color
        this.textColor = textColor
        this.name = name
        this.x = x
        this.y = y
        this.width = width
        this.height = height
        this.fontSize = fontSize
        
        let translateX = width/2
        let translateY = height/2
        
        //Define the button Style
        context.translate(translateX, translateY)
        context.fillStyle = color
        context.fillRect(x,y,width,height)
            
        //Define how the button text will be draw, (just put nothing at the creation of especified and it will not have a text on it.)  
        context.fillStyle = textColor
        context.font = "bold 14px arial"
        context.translate(width/2 - 14  ,height/2)
        context.fillText(name,x,y, fontSize) 
        
        //Debug
        console.log("The > " + "!" + name + "!" + " width is " + textWidth)
        console.log("The > " + "color of " + name + " is: " + color)
        console.log("The > " + "text color of " + name + " is: " + textColor)
        console.log("The > " + "position X of " + name + " is: " + x)
        console.log("The > " + "position Y of " + name + " is: " + y)
        console.log("The > " + "width of " + name + " is: " + width)
        console.log("The > " + "height of " + name + " is: " + height)
        console.log("The > " + "font size of " + name + " is: " + fontSize)
        console.log("The > " + "translate X of " + name + " is: " + translateX)
        console.log("The > " + "translate Y of " + name + " is: " + translateY)
        
    }
}

function draw(){
    
        scene = level[0]
    
        context.fillStyle = "gray"
        context.fillRect(0,0,500,500)
        
        if(scene == level[0]){
            const start = new Button("white","black","start",500/2, 100, 100, 30, 30)
            const start0 = new Button("white","black","start1",500/2, 100, 100, 30, 30)
            const testZero = new Button("white","black","",500/2, 100, 100, 30, 30)
        }
        
}

That's the code. When I run it in my browser, it looks like this:

Here

Although the buttons have the same x and y, they change its x by little, and I don't know what it is. If you know, please tell me. I will be grateful.

I expected it to go for the center of its origin, and simply go for the center with only (500/2), but it won't.


Solution

  • Funny how the debug is just to output the input of the function, it shows you ran out of ideas ...

    I second @CBroe comment, no need for translate, that is just complicating your code, we can do all that at the correct location

    When you are troubleshooting/debugging your code go simple, for example if the issue is not with the font and the text, remove all that, leave your code to as minimal as you can, must of the time you will realize where the problem is or a workaround, if not you will have a small example you can show to others.

    Here is some working code:

    const canvas = document.getElementById('x');
    const context = canvas.getContext('2d');
    
    
    class Button {
      constructor(color, x, y, width, height) {
        context.fillStyle = color
        context.fillRect(x, y, width, height)
      }
    }
    
    
    new Button("red",   10,  10, 60, 30)
    new Button("blue",  10,  60, 60, 30)
    new Button("green", 10, 110, 60, 30)
    
    new Button("red",   170, 10, 50, 20)
    new Button("blue",  170, 40, 50, 20)
    new Button("green", 170, 70, 50, 20)
    <canvas id="x" width="400" height="180"></canvas>

    Once you get the basic working you can add the next step like a centered text on the button

    const canvas = document.getElementById('x');
    const context = canvas.getContext('2d');
    
    
    class Button {
      constructor(color, x, y, width, height) {
        context.fillStyle = color
        context.fillRect(x, y, width, height)
    
        context.font = "bold 40px arial"
        context.textAlign = "center";
        context.textBaseline = "middle";
        context.strokeText(color, x + width / 2, y + height / 2)
      }
    }
    
    
    new Button("red", 10, 10, 140, 60)
    new Button("cyan", 10, 100, 140, 60)
    new Button("green", 180, 10, 140, 60)
    <canvas id="x" width="400" height="180"></canvas>


    Now if you are building a game maybe you should consider using a proper game engine:
    https://github.com/collections/javascript-game-engines
    That will save you a lot of time and headaches