observablehq / stdlib

The Observable standard library.
https://observablehq.com/@observablehq/standard-library
ISC License
966 stars 83 forks source link

DOM.context2d producing canvas of wrong dimensions #188

Closed ov212 closed 3 years ago

ov212 commented 3 years ago

Hi all - I think DOM.context2d() is returning the wrong dimensions.

{
  const context = DOM.context2d(960, 500);
  return context.canvas;
}

Produces the following html:

<canvas width="768" height="400" style="width: 960px;"></canvas>

instead of a 960×500 canvas as stated in the documentation

(Meanwhile DOM.canvas() works as expected

{
  const canvas = DOM.canvas(960, 500);
  const context = canvas.getContext('2d');
  return context.canvas;
}

produces <canvas width="960" height="500"></canvas> )

mbostock commented 3 years ago

You can find the entire source of DOM.context2d here:

https://github.com/observablehq/stdlib/blob/master/src/dom/context2d.js

Inline:

function(width, height, dpi) {
  if (dpi == null) dpi = devicePixelRatio;
  var canvas = document.createElement("canvas");
  canvas.width = width * dpi;
  canvas.height = height * dpi;
  canvas.style.width = width + "px";
  var context = canvas.getContext("2d");
  context.scale(dpi, dpi);
  return context;
}

As you can see, the behavior of DOM.context2d is by default dependent on the value of window.devicePixelRatio, which appears to be 0.8 for you (which is a little unusual; more common values are 2 and 1). If you don’t want this behavior, you can pass dpi explicitly:

const context = DOM.context2d(960, 500, 1);
ov212 commented 3 years ago

All makes sense - thanks!