I haven’t found out why, but it seems specifically in observable, scaling a canvas element with css transforms results in an inconsistent canvas size:
If you drag the slider, you’ll see the black canvas jumping.
Here’s a jsfiddle with the same code, without jumpiness:
https://jsfiddle.net/jasperh/zp98e207/
A work-around is by instead of using css-transform scaling, just giving the canvas a static width/height in css (i.e. not the width/height html attribute). But I thought it might still be good to fix this if it’s an observable specific thing.