How to implement letterbox scaling in PixiJS
Nassim
When making a game you usually want to preserve an aspect ratio regardless of the size of the player's screen. This is called letterbox scaling.
Here is an example. Down below is an implementation in PixiJS.
Here is the CSS you need :
html, body {
background: black;
}
#pixi-canvas {
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
margin: auto;
}
Now here is the JS code :
import { Application, Sprite, SCALE_MODES} from 'pixi.js'
const logicalWidth = 160
const logicalHeight = 144
const app = new Application({
width: logicalWidth,
height: logicalHeight,
resolution: window.devicePixelRatio || 1,
background: '#1099bb'
})
app.view.id = 'pixi-canvas'
document.body.appendChild(app.view)
const bunny = Sprite.from('https://s3-us-west-2.amazonaws.com/s.cdpn.io/169700/bunny.png')
bunny.x = logicalWidth / 2
bunny.y = logicalHeight / 2
bunny.anchor.x = 0.5
bunny.anchor.y = 0.5
bunny.texture.baseTexture.scaleMode = SCALE_MODES.NEAREST
function resizeHandler() {
const scaleFactor = Math.min(
window.innerWidth / logicalWidth,
window.innerHeight / logicalHeight
)
const newWidth = Math.ceil(logicalWidth * scaleFactor)
const newHeight = Math.ceil(logicalHeight * scaleFactor)
app.view.style.width = `${newWidth}px`
app.view.style.height = `${newHeight}px`
app.scale.set(scaleFactor)
}
app.stage.addChild(logo)
app.ticker.add(() => {
bunny.rotation += 0.01
})
window.addEventListener('resize', resizeHandler, false)
resizeHandler()
Observations
logicalWidth
and logicalHeight
are the width and height we original design for. Here I've used the original width and height of the Game Boy.
resizeHandler
contains the math needed to pull off letterbox scaling.
A bit of a tagent but you'll notice the use of SCALE_MODES.NEAREST
on the bunny's texture. This is what you need to use when displaying pixelart so it won't become blurry.
That's pretty much it for the observations. Hope this is useful.