キャンバスの Retinaディスプレイ対応 deprecated
macOS Catalina 10.15.7 にアップグレードしたところ、本章で説明した対応は必要なくなった。おそらく OS側で対応しているのだろう。逆に Catalina以降でこの対応をとると Retainディスプレイの表示が通常の2倍になってしまうという不具合が生じる。OSのバージョンによって対応の有効/無効を切り替えたいところだが、JavaScriptから判定するのはかなり難しそうではある。
MacBook Pro (Retina, 13-inch, Early 2015) / macOS Mojava 10.14.6
図形や文字を描画したキャンバスを Macの 高解像度 Retainディスプレイに表示すると画像が滲んでしまう。Retainディスプレイは、通常のディスプレイの2倍の解析度を誇っているのだが、その故に、通常の描画方法では、正しく表示できない、一般のディスプレイより見た目が悪くなるという本末転倒なことが起こってしまう。
対応を簡単にいうと、サイズを 2倍にしたキャンバスに描画を行い、それを2分の1に縮小して表示するということになる。
canvasタグの定義
実キャンバスのサイズ と表示上のキャンバスのサイズ(style属性)は両方とも冗長であるが必ず指定すること。ここがポイント。
JavaScript
Retinaディスプレイに対応するキャンバスのコンテキストを返す関数
関数の引数に canvas要素を渡すと、ディスプレイの解析度に応じたコンテキストが返る。これに対して、ディスプレイの違いを意識することなく描画を行うことができる。
window.devicePixelRatioプロパティは、CSS解像度と物理解像度の比を返す。通常の伝統的なディスプレイは1、Retainディスプレイは2を返す。Retainディスプレイは通常のディスプレイに比べて2倍の解像度を持つという意味である。ものによっては 2を超える超解析度のディスプレイもあるらい。
スケールが 1の場合は通常の方法でコンテキストを返す。
スケールが 1以外の場合、実キャンバスのサイズとコンテキストのサイズをスケール倍し、コンテキストを返す。
仕組みとしては、2倍したサイズ 1260 x 500 のキャンバスに描画した画像を、サイズ 630 x 250 のキャンバスに描き出すということになる。前者は実キャンバスのサイズ、後者は style属性で定義した表示上のキャンバスサイズに対応する。
実際の表示例
上が Retainディスプレイ対応をしてキャンバスに描画したもの、下がしないでキャンバスに描画したものである。 通常のディスプレイでは両者は同じであるが、Macの Retainディスプレイで表示してみれば、上は鮮明に、下はぼやけて表示されるのがわかるはずである。
Retainディスプレイ対応
非 Retainディスプレイ対応
次の画像は、Retainディスプレイのスクリーンショットを拡大したものである。上が Retainディスプレイ対応をしたキャンバス、下がしないキャンバスである。違いがはっきりわかるのではないだろうか。


実装コード
Retinaディスプレイ対応の getContext関数は drawing.jsライブラリに RetinaDisplayクラスの Staticメソッドとして定義する。こちらの使用方法は キャンバスに構造図を描くツール で説明している。