HTML
JavaScript
HTML5
canvas

本当は怖い HTML5 Canvas の Retina対応

More than 5 years have passed since last update.

モバイル向けに、Canvasでつくったゲームを

Retinaディスプレイ対応をしたときにハマったこと。


CanvasのRetina対応は一筋縄にはいかないッ

基本的にCanvasのRetina対応は以下のように、

実際のサイズの2倍のサイズでつくったCanvas要素を、CSSで実際のサイズに縮める。


HTML

<canvas id="sample_canvas" width="640" height="800" style="width: 320px; height: 400px"></canvas>


これで、Retinaディスプレイできれいに表示できる。

しかし、このままでは以下のような問題が起きちゃう。


  • 2倍のサイズのCanvasに描画を行うため、処理が重くなる

  • そのため 一部のAndroid端末にて、ブラウザが落ちる、端末が発熱する

  • 一部のAndroid端末にて、Canvas要素のstyle属性を動的に変更するとブラウザが落ちる

そこで、Retina以外の端末向けに、処理の切り分けが必要になる。

Canvas要素は実際のサイズ。Canvas上の座標系をあわせるために、

Canvasのscaleを0.5にする。


HTML

<canvas id="sample_canvas" width="320" height="400"></canvas>



JavaScript

var canvas  = document.getElementById("sample_canvas");

var context = canvas.getContext("2d");

context.scale(0.5,0.5);


これで、Canvas内の座標は同じ数値を指定できるようになる。

window.devicePixelRatioの値に応じてCanvasサイズを決める方法もあるが、

上記のstyle属性をいじると落ちるバグがあるため、

iOSのRetinaディスプレイとそれ以外で切り分けるのがおすすめ。



その他 注意すること


widthとheightは変更しない

一部のAndroid端末では、Canvas要素のwidthとheightを変更すると、

Canvasの描画が2重になり、clearRect してもクリアされないというバグがある。

一度設定したwidthとheightは変更しないッ(再代入はOK


drawImage での縮小だと画像がボケる

Canvas APIのdrawImageでも、2倍の大きさの画像を実際のサイズに縮小して表示できる。


JavaScript

var image = new Image();

image.src = "sample.png"; // 実際のsample.pngのサイズ 200x200

image.addEventListener("load", function() {

context.drawImage(image,0,0,100,100); // 半分のサイズを指定

}, false);


しかし、これだとCanvas上のピクセルは2倍にならないため

Retinaディスプレイでは画像がボケる。



まとめ

今回は、Android端末にも広く対応を考えた場合に必要な話なので、

対応端末が限られる場合(iOSだけとか)の場合は気にする必要なしッ

とはいえ、結構シェアの高い端末でも発生する問題だったりします...!