Android (Using Ionic + Capacitor) is not resizing the canvas to fit the screen with Phaser.Scale.RESIZE, but kinda does with WIDTH_CONTROLS_HEIGHT

I’m using Ionic, React, and Capacitor to make something with Phaser - it all works perfectly in the browser on desktop, but when I try to run the Android project with an emulator - Ionic and React load just fine, but the Phaser canvas is just a thin black (The background color for the canvas) bar, about 20px tall, with the Phaser logo bouncing up and down (The default scene).

However! When I use Scale: { mode: Phaser.Scale.WIDTH_CONTROLS_HEIGHT }, the Phaser canvas fits the screen! …Well, and then some. It fits the width properly as far as I can tell, but the canvas goes well off the screen on the bottom, so the Phaser logo bounces off the screen briefly then returns when viewing the default scene.

React game component:

import React, { useState, useRef, useEffect } from 'react';
import {
	IonContent, IonFab, IonFabButton,
	IonHeader,
	IonMenuButton,
	IonPage,
	IonTitle,
	IonToolbar,
} from '@ionic/react';
import { IonPhaser } from '@ion-phaser/react';

import playGame from '../phaser/scene';

const DEFAULT_HEIGHT = window.innerHeight;
const DEFAULT_WIDTH = window.innerWidth;

const gameContentWrapper = {
	width: '100%',
	height: '100%',
	margin: 'auto',
	padding: 0,
	overflow: 'hidden',
};

const gameCanvas = {
	width: '100%',
	height: '100%',
	margin: 'auto',
	imageRendering: 'pixelated',
};

const gameConfig = {
	type: Phaser.AUTO,
	width: DEFAULT_WIDTH,
	height: DEFAULT_HEIGHT,
	orientation: Phaser.Scale.LANDSCAPE,
	autoRound: true,
	autoFocus: true,
	// disableContextMenu: true,
	render: {
		pixelArt: true,
	},
	scale: {
		autoCenter: Phaser.Scale.CENTER_BOTH,
		mode: Phaser.Scale.RESIZE,
		// mode: Phaser.Scale.WIDTH_CONTROLS_HEIGHT,
	},
	backgroundColor: '#000',
	scene: playGame,
};

function Game() {
	const gameRef = useRef(null);
	const [initialize, setInitialize] = useState(false);
	
	const destroy = () => {
		if (gameRef.current) {
			gameRef.current.game.destroy();
		}
		setInitialize(false);
	};
	
	function resize() {
		console.log(gameRef.current);
		if (!gameRef.current) {
			return;
		}
		
		const {game} = gameRef.current;
		const canvas = gameRef.current.children[0];
		
		game.width = window.innerWidth;
		canvas.style.width = window.innerWidth;
		game.height = window.innerHeight;
		canvas.style.height = window.innerHeight;
	}
	
        // Called when the DOM is finished loading
	useEffect(() => {
		setInitialize(true);
		window.addEventListener('resize', resize);
		window.addEventListener('load', resize);
		return () => {
			destroy();
		};
	}, []);
	
	return (
		<IonPage>
			<IonFab vertical="top" horizontal="start" slot="fixed">
				<IonFabButton>
					<IonMenuButton auto-hide="false" menu="mainMenu" mode="md" />
				</IonFabButton>
			</IonFab>
			
			<IonContent fullscreen>
				<div style={gameContentWrapper}>
					<IonPhaser ref={gameRef} game={gameConfig} initialize={initialize} style={gameCanvas} />
				</div>
			</IonContent>
		</IonPage>
	);
}

export default Game;

scene.js

import Phaser from 'phaser';
import logoImg from '../assets/logo.png';

class playGame extends Phaser.Scene {
	constructor() {
		super('PlayGame');
	}

	preload() {
		this.load.image('logo', logoImg);
	}

	create() {
		const logo = this.add.image(400, 150, 'logo');

		this.tweens.add({
			targets: logo,
			y: 450,
			duration: 2000,
			ease: 'Power2',
			yoyo: true,
			loop: -1,
		});
	}
}

export default playGame;

I’m just using the basic Ionic menu + React starter template, with the following route added:

					<Route path="/game" exact>
						<Game />
					</Route>

Is there any way to get Phaser.Scale.RESIZE to work properly on Android? WIDTH_CONTROLS_HEIGHT seems problematic and I’d really just like the canvas to fill the screen width and height regardless of aspect ratio.

I’m using the latest versions of Ionic, Capacitor, and Phaser.

If you’re curious what IonPhaser is, check here - I updated it to work with the latest version of React, but other than that it’s exactly the same. It’s just a simple wrapper to make Phaser more React friendly.

The gameRef is a reference to the IonPhaser container, which has the game object and the canvas (children[0]) in an object - everything else is exactly the same as normal Phaser.

edit: The same issue occasionally appears when the devtools are open in Firefox Desktop, but go away when the devtools are closed or the screen is resized

:wave:

You have to look at the DOM/styles to see what’s going on. Or phaser-plugin-debug-game-scale may tell you something.

With all of the scale modes besides NONE you really aren’t supposed to be setting the canvas styles/dimensions; that’s what the Scale Manager is doing. You can do

this.scale.refresh();

or

game.scale.refresh();

if you know that the DOM layout has changed.

If you want something like canvas.style.width = window.innerWidth then I would try scale mode FIT.

game.scale.refresh()

Didn’t exist, so I’m not sure if that’s an issue with IonPhaser or what. So I tried:

game.instance.scale.refresh();

Which DOES exist, but now it doesn’t resize properly in desktop. It has the same thin line issue, until I close devtools - then it resizes to the size of the screen when devtools was open until the entire window is resized. The resize() function is called when the page is finished loading, when the devtools are opened/closed, when the window is resized, etc…

edit: Also the issue occurs without devtools being opened now.

edit: Chrome has similar issues, but doesn’t resize at all when the browser window size changes.

edit again: It seems like updating the game height and width manually is … Updating the game height and width, since the logo bounces off screen when it’s not filling the area.

another edit: Now if I try to update the canvas style height/width, but call refresh() after - it no longer properly changes the canvas size on desktop - just the game size. It works as intended when I remove refresh() though (Again, on Firefox Desktop)

One more edit: I forgot to mention, when I inspect the canvas element in Chrome devtools’ android debugger, it says the height is 17. Same with Firefox desktop’s devtools when it’s got the thin black line issue.