Phaser 3 Container Size – Get Height and Width

How do you get the height and width of a container? If you’ve been playing around with Phaser 3 containers for a while, and are accustomed to using Phaser 2 groups, you may notice some familiar things missing. A few months ago I added some sprites to a container for building some user interface components. I needed to know the container size, so I could line things up properly and found that the width wasn’t set. Here is an example of what I mean.

First let’s start by preloading some images, and placing them on the stage and adding them inside a container

class SceneMain extends Phaser.Scene {
    constructor() {
        super('SceneMain');
    }
    preload() {
        for (var i = 0; i < 4; i++) {
            this.load.image("dot" + i, "images/" + i + ".png");
        }
    }
    create() {
        this.container = this.add.container();
        this.dot1 = this.add.image(100, 250, "dot0");
        this.dot2 = this.add.image(400, 250, "dot1");
        //
        //
        this.dot3 = this.add.image(100, 400, "dot2");
        this.dot4 = this.add.image(400, 400, "dot3");
        //
        //
        //
        this.container.add(this.dot1);
        this.container.add(this.dot2);
        this.container.add(this.dot3);
        this.container.add(this.dot4);
        //
        //        
        console.log(this.container);
    }
}
Dots in a container

Inspecting the container

When we look in the developer console where we logged out the container and locate the displayWidth and displayHeight properties, we can see that the values are 0. (You’ll need to click the …).

Containers do not update their size, but it can be done manually. This can be done by using the setSize method of the container class. First, though we need to know what the size is. If we are making something like a message box, or anything that has a square background we can use the background’s size for the container. If we have several sprites inside like the example above we need to use some simple maths to accomplish this.

Calculate the container size

To get the size we need to make a square out the sprites. We can do this by getting the extreme positions of all the child sprites of the container. By this I mean the topmost, bottom most, and the greatest left and right positions.

getSize(con) {
        //set the top position to the bottom of the game
        var top = game.config.height;
        var bottom = 0;
        //set the left to the right of the game
        var left = game.config.width;
        var right = 0;
        //
        //
        //loop through the children
        //
        con.iterate(function(child) {
            //get the positions of the child
            var childX = child.x;
            var childY = child.y;
            //
            //
            //
            //test the positions against
            //top, bottom, left and right
            //
            if (childY > bottom) {
                bottom = childY;
            }
            if (childY < top) {
                top = childY;
            }
            if (childX < left) {
                left = childX;
            }
            if (childX > right) {
                right = childX;
            }
        }.bind(this));

        //calculate the square
        var h = Math.abs(top - bottom);
        var w = Math.abs(right - left);

        //set the container size
        con.setSize(w, h);
    }

Usage

In the create function call the following code

 this.getSize(this.container);
 console.log(this.container);

Now when we log out the container, we can see the size has been set to 300 for the displayWidth and 150 for the displayHeight.

More Precision

While this gives us a size, it is not an exact size because it doesn’t take the origin of the image into account. Let’s add in that part now.

getSize(con) {
        //set the top position to the bottom of the game
        var top = game.config.height;
        var bottom = 0;
        //set the left to the right of the game
        var left = game.config.width;
        var right = 0;
        //
        //
        //loop through the children
        //
        con.iterate(function(child) {
            //get the positions of the child
            var childX = child.x;
            var childY = child.y;
            //
            //
            //
            var childW = child.displayWidth;
            var childH = child.displayHeight;
            //
            //
            //calcuate the child position
            //based on the origin
            //
            //
            var childTop = childY - (childH * child.originY);
            var childBottom = childY + (childH * (1 - child.originY));
            var childLeft = childX - (childW * child.originX);
            var childRight = childX + (childW * (1 - child.originY));
            //test the positions against
            //top, bottom, left and right
            //
            if (childBottom > bottom) {
                bottom = childBottom;
            }
            if (childTop < top) {
                top = childTop;
            }
            if (childLeft < left) {
                left = childLeft;
            }
            if (childRight > right) {
                right = childRight;
            }
        }.bind(this));
        //
        //calculate the square
        var h = Math.abs(top - bottom);
        var w = Math.abs(right - left);        
        //set the container size
        con.setSize(w, h);
    }

Testing the code

Now how can we make sure that this is getting the container size correctly? Let’s draw a square based on the positions, just to test it out. Add this code to the end of the getSize function

this.graphics = this.add.graphics();
this.graphics.fillStyle(0xff00ff, .4);
this.graphics.fillRect(left,top,w,h);
container size shown by the square here

More Testing

This works well for our dots that are already in a square, but will it work if we more the dots? That’s the beauty of using maths to find the container size. Let’s change how we are placing the dots. Let’s add the dots into random positions. Replace the code in the create function with the following code:

create() {
        this.container = this.add.container();
        for (var i = 0; i < 4; i++) {
            var xx = Phaser.Math.Between(200, 400);
            var yy = Phaser.Math.Between(100, 500);
            var dot = this.add.image(xx, yy, "dot" + i);
            this.container.add(dot);
        }
        this.getSize(this.container);       
}

And here is the result

random container size
Random

Leave a Comment