Last active
April 9, 2025 20:22
-
-
Save callumlocke/cc258a193839691f60dd to your computer and use it in GitHub Desktop.
How to fix a canvas so it will look good on retina/high-DPI screens.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
UPDATED for 2023 - Now much simpler. The old tricks are no longer needed. | |
The following code makes an 800×600 canvas that is always as sharp as possible for the device. | |
You still draw on it as if it's the logical size (800×600 in this case), but everything just | |
looks sharper on high-DPI screens. Regular non-sharp screens are not affected. | |
*/ | |
const width = 800 | |
const height = 600 | |
const canvas = document.createElement('canvas') | |
const ctx = canvas.getContext('2d') | |
// 1. Multiply the canvas's width and height by the devicePixelRatio | |
const ratio = window.devicePixelRatio || 1 | |
canvas.width = width * ratio | |
canvas.height = height * ratio | |
// 2. Force it to display at the original (logical) size with CSS or style attributes | |
canvas.style.width = width + 'px' | |
canvas.style.height = height + 'px' | |
// 3. Scale the context so you can draw on it without considering the ratio. | |
ctx.scale(ratio, ratio) |
Thanks, this saved me a lot of time!
If it helps anyone I did a lil' refactor in typescript also including some of @j2is changes.
Seems to me that the .backingStorePixelRatio
is deprecated(?), so I removed that as well.
function scaleCanvas(
canvas: HTMLCanvasElement,
context: CanvasRenderingContext2D,
width: number,
height: number
) {
// Handle window for SSR
if (typeof window === 'undefined') return null
// determine the actual ratio we want to draw at
const ratio = window.devicePixelRatio || 1
if (devicePixelRatio !== 1) {
// set the 'real' canvas size to the higher width/height
canvas.width = width * ratio
canvas.height = height * ratio
// ...then scale it back down with CSS
canvas.style.width = width + 'px'
canvas.style.height = height + 'px'
} else {
// this is a normal 1:1 device; just scale it simply
canvas.width = width
canvas.height = height
canvas.style.width = ''
canvas.style.height = ''
}
// scale the drawing context so everything will work at the higher ratio
context.scale(ratio, ratio)
}
This worked better for me because it scale the context too! :
function createHiPPICanvas(width, height) {
const ratio = window.devicePixelRatio;
const canvas = document.createElement("canvas");
canvas.width = width * ratio;
canvas.height = height * ratio;
canvas.style.width = width + "px";
canvas.style.height = height + "px";
canvas.getContext("2d").scale(ratio, ratio);
return canvas;
}
from https://stackoverflow.com/questions/15661339/how-do-i-fix-blurry-text-in-my-html5-canvas
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Nice
I didn't pass in the width and height but grab that from within the function
did a check when there might not be a window (SSR)
call this function on resize