In this Phaser 3 example, I step away from sprites and plans for collisions as I am working on something this fits in well with. I need a toolbar for another project and created a short example scene.

I was looking at creating a toolbar for another side project and found to be close to what I imagined.

The example is for opening multiple scenes, which is not quite what I needed. I just wanted a draggable container I could add buttons/controls to.

toolbar scene image
Phaser 3 Toolbar Scene
class ToolbarScene extends Phaser.Scene {
//phaser 3 toolbar example scene
private toolbarContainer: Phaser.GameObjects.Container;
private rotateCcw: Phaser.GameObjects.Image;
private rotateCw: Phaser.GameObjects.Image;
private windmill: Phaser.GameObjects.Image;
constructor() {
key: 'ToolbarScene'
preload() {
console.log('Toolbar scene preload');
//made by me just a simple rectangle - CC0
this.load.image('toolbar', '/assets/toolbar.png');
//rotate-cw and rotate-ccw from
this.load.image('rotate-cw', '/assets/rotate-cw.png');//rotate clockwise
this.load.image('rotate-ccw', '/assets/rotate-ccw.png');//rotate counter clockwise
//picture of windmill near Vantage Washington taken by me sometime in August 2019 - CC0
this.load.image('windmill', '/assets/windmill.jpg');
create() {
let menuItem: Phaser.GameObjects.Text = this.add.text(15, 10, "Home", 
{ fontFamily: 'Verdana, "Times New Roman", Tahoma, serif', fontSize: 25, color: '#3333ff' });
menuItem.setInteractive({ cursor: 'pointer' }).on('pointerdown', () => {
window.history.replaceState({}, 'Phaser 3 Examples', './');
let toolbar = this.add.image(0, 0, 'toolbar').setOrigin(0);
this.rotateCcw = this.add.image(25, 10, 'rotate-ccw').setOrigin(0).setInteractive({ cursor: 'pointer' });
this.rotateCw = this.add.image(25, 50, 'rotate-cw').setOrigin(0).setInteractive({ cursor: 'pointer' });
this.toolbarContainer = this.add.container(15, 50, [toolbar, this.rotateCw, this.rotateCcw]);
this.toolbarContainer.setInteractive(new Phaser.Geom.Rectangle(0, 0, toolbar.width, toolbar.height), Phaser.Geom.Rectangle.Contains);
this.windmill = this.add.image(screen.width / 2, screen.height / 2, 'windmill');
//pointer isn't used but in testing it is required or things go wrong. using _pointer to avoid the warning of unused parameter.
this.toolbarContainer.on('drag', function (_pointer: Phaser.Input.Pointer, dragX: number, dragY: number) {
this.x = dragX;
this.y = dragY;
});//not binding to this as the this we want is toolbarContainer. If I bound to this then we'd need this.toolbarContainer.x ...
this.windmill.on('drag', function (_pointer: Phaser.Input.Pointer, dragX: number, dragY: number) {
this.x = dragX;
this.y = dragY;
this.rotateCcw.on('pointerdown', function () {
this.windmill.angle -= 1;
}, this); //binding to this as we need to access outside of rotateCcw
this.rotateCw.on('pointerdown', function () {
this.windmill.angle += 1;
}, this); // could use () => {} and not bind, but following
export default ToolbarScene;

Phaser 3 Example Toolbar Scene

The spin clockwise / counterclockwise images came from some from me.

Full project source code at

In this latest commit Phaser 3 was updated to 3.19.0 Phaser v3.19.0-FB (WebGL | Web Audio)

Leave a comment

Your email address will not be published. Required fields are marked *