Adjust Pixel Ratio for High DPI in Matter.js
High-DPI and Retina displays often render standard HTML5 canvases
with blurry or pixelated visuals because the physical screen pixels
outnumber the logical CSS pixels. In Matter.js, you can easily fix this
issue by configuring the pixelRatio property within the
renderer settings. This article explains how to configure and adjust the
pixel ratio during initialization and dynamically update it to ensure
crisp, sharp rendering across all displays.
Setting Pixel Ratio on Initialization
When creating a renderer using Matter.Render.create(),
pass the pixelRatio option inside the options
object. You can either set it to 'auto' to let Matter.js
detect the screen density automatically, or explicitly pass
window.devicePixelRatio.
const { Engine, Render, Runner, Bodies, Composite } = Matter;
const engine = Engine.create();
// Create the renderer with high DPI support
const render = Render.create({
element: document.body,
engine: engine,
options: {
width: 800,
height: 600,
wireframes: false,
pixelRatio: window.devicePixelRatio || 1 // or simply 'auto'
}
});
Render.run(render);
Runner.run(Runner.create(), engine);How Matter.js Handles Pixel Ratio
When pixelRatio is greater than 1,
Matter.js automatically scales the underlying HTML5
<canvas> element:
- Drawing Buffer: It multiplies the internal canvas
resolution (
canvas.widthandcanvas.height) by the specified pixel ratio to match physical screen pixels. - Display Size: It sets the CSS styling
(
canvas.style.widthandcanvas.style.height) to your target dimensions (e.g., 800x600 px). - Context Scale: It scales the 2D drawing context so that coordinates in your physics world continue to map 1:1 with logical screen coordinates, preserving the positions and sizes of your bodies without requiring manual transformation.
Updating Pixel Ratio Dynamically
If users drag the browser window between displays with different
pixel densities (such as moving from an external 1080p monitor to a
built-in Retina display), you can update the ratio on the fly using
Matter.Render.setPixelRatio():
function updatePixelRatio(render) {
const newRatio = window.devicePixelRatio || 1;
Render.setPixelRatio(render, newRatio);
}
// Listen for resolution changes
window.matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`)
.addEventListener('change', () => {
updatePixelRatio(render);
});Using Matter.Render.setPixelRatio() ensures that the
canvas buffer size, styles, and context transforms are updated
immediately without needing to recreate the entire physics engine or
renderer instance.