'Change element size and position according to window resize updates in canvas

I am pretty new to Javascript, but not to programming in general. I am creating a game using Javascript's built-in CanvasRenderingContext2D.

Because I need to update the view every 1/60th of a second, I am running an animation loop, and storing all objects I need to draw in an array. Then executing drawChildren() to go through every child in the list and draw it. Because of this, I don't know how to access and update the child's XY position and size.

What I want to achieve is, that every time the window gets resized, it iterates through the list of objects and updates their position to stay where they were before.

I have everything in one Javascript file.

game.js

const canvas = document.querySelector("#canvas")
const ctx = canvas.getContext("2d")
canvas.width = window.innerWidth
canvas.height = window.innerHeight



var images = []
var children = []
var w = canvas.width
var h = canvas.height
const clearStyle = 'rgb(255, 255, 255)'



class childObject {
    constructor(x, y, w, h) {
        this.style = 'black'
        this.x = x
        this.chposition = -1
        this.y = y
        this.w = w
        this.h = h
        this.tag = 'unnamed object'
    }
    destroy() {
        if (this.chposition == -1) {
            return
        } else {
            children.splice(this.chposition, 1)
        }
    }
}

class childRect extends childObject {
    constructor(x, y, w, h) {
        super(x, y, w, h)
        this.x = x
        this.y = y
        this.w = w
        this.h = h
    }
}

class childImage extends childObject {
    constructor(img, x, y) {
        super(x, y, 0, 0)
        this.img = img
        this.x = x
        this.y = y
        this.pos = 0
        this.useCustomSize = false
        this.temp = new Image()
        this.itag = 'undefined itag'
    }
    load() {
        this.temp.src = this.img
    }
    push() {
        images.push(this.temp)
    }
}

class childButton extends childObject {
    constructor(x, y, w, h) {
        super(x, y, w, h)
        this.x = x
        this.y = y
        this.w = w
        this.h = h
        this.defaultStyle = 'rgb(200, 200, 200)'
        this.hoveredStyle = 'rgb(128, 128, 128)'
        this.clickedStyle = 'rgb(240, 240, 240)'
        this.textStyle    = 'rgb(0, 0, 0)'
        this.onclick = () => {}
        this.isHoveredOver = false
        this.style = this.defaultStyle
        this.title = 'Button'
        this.isClicked = false
        this.font = 'default'
    }
}

class childLabel extends childObject {
    constructor(text, x, y) {
        super(x, y, 0, 0)
        this.x = x
        this.y = y
        this.text = text
        this.font = 'default'
        this.textStyle = 'black'
    }
}

class Scenery {
    constructor() {
        
    }
    scene_start() {
        const Geographer = new childLabel('Game.io', w / 2 - (ctx.measureText('Game.io').width), h / 2 - 50)
        Geographer.font = '28px Arial'
        addChild(Geographer)
    }
}


function setup() {
    loadEvents()
    const SceneManager = new Scenery()
    SceneManager.scene_start()
}

function findChild(tag) {
    for (const child of children) {
        if (child.tag == tag) {
            return child
        }
    }
    return null
}

function findImage(tag) {
    for (const img of images) {
        if (img.itag == tag) {
            return img
        }
    }
    return null
}

function addChild(child) {
    children.push(child)
    child.chposition = children.length - 1
}

function mouseMove(e) {
    for (const child of children) {
        if (child.constructor.name == 'childButton') {
            if (e.clientX > child.x && e.clientX < child.x + child.w && e.clientY > child.y && e.clientY < child.y + child.h + 2) {
                child.isHoveredOver = true
                if (child.isClicked == false) {
                    child.style = child.hoveredStyle
                }
            } else {
                child.isHoveredOver = false
                child.style = child.defaultStyle
            }
        }
    }
}

function mouseDown() {
    for (const child of children) {
        if (child.constructor.name == 'childButton') {
            if (child.isHoveredOver == true) {
                child.style = child.clickedStyle
                child.isClicked = true
            }
        }
    }
}

function mouseUp() {
    for (const child of children) {
        if (child.constructor.name == 'childButton') {
            if (child.isHoveredOver == true) {
                child.style = child.hoveredStyle
                child.isClicked = false
            } else {
                child.style = child.defaultStyle
            }
        }
    }
}

function click() {
    for (const child of children) {
        if (child.constructor.name == 'childButton') {
            if (child.isHoveredOver == true) {
                child.onclick()
            }
        }
    }
}

function contextMenu(e) {
    e.preventDefault()
}

function loadEvents() {
    canvas.addEventListener('mousemove', mouseMove)
    canvas.addEventListener('mousedown', mouseDown)
    canvas.addEventListener('mouseup', mouseUp)
    canvas.addEventListener('click', click)
    canvas.addEventListener('contextmenu', contextMenu)
}

function update() {
    
}

function drawChildren() {
    for (const child of children) {
        if (child.constructor.name == 'childRect') {
            ctx.fillStyle = child.style
            ctx.fillRect(child.x, child.y, child.w, child.h)
        } else if (child.constructor.name == 'childImage') {
            child.useCustomSize ? ctx.drawImage(images[child.pos], child.x, child.y, child.w, child.h) : ctx.drawImage(images[child.pos], child.x, child.y)
        } else if (child.constructor.name == 'childButton') {
            ctx.fillStyle = child.style
            ctx.fillRect(child.x, child.y, child.w, child.h)
            ctx.fillStyle = child.textStyle
            if (child.font != 'default') {
                ctx.font = child.font
            }
            ctx.fillText(child.title, child.x + (child.w / 2 - (ctx.measureText(child.title).width)/2), child.y + (child.h / 2) + 2)
        } else if (child.constructor.name == 'childLabel') {
            ctx.fillStyle = child.textStyle
            if (child.font != 'default') {
                ctx.font = child.font
            }
            ctx.fillText(child.text, child.x, child.y)
        }
    }
}

function erase() {
    ctx.fillStyle = clearStyle
    ctx.fillRect(0, 0, w, h)
}

function loop() {
    erase()
    update()
    drawChildren()
    window.requestAnimationFrame(loop)
}



window.addEventListener('resize', function() {  
    w = window.innerWidth;
    h = window.innerHeight;
    canvas.width = w;
    canvas.height = h; 
})



setup()
loop()
window.requestAnimationFrame(loop)

I am not sure if posting the HTML code is necessary, too, as it only has the <script> referencing the source code and a canvas.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source