'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 |
|---|
