1. ホーム
  2. Web制作
  3. html5

キャンバスの描画がぼやける問題の解決法

2022-01-28 19:42:51

にじみの原因

まず、キャンバスの表示メカニズムについて理解する必要があります。

<canvas id="map" width="375" height="667"></canvas>

キャンバスを375pxで描きましたが、iphone6の幅も375pxです、OK、キャンバスが画面全体に広がります。

すると、キャンバスの大きさは375pxになります。キャンバスは絵に似ている、375pxの絵だ、と思って見ましょう。私、昆 TSTが言ったように。

もし、画面幅400pxのスマホに遭遇したら、画像は伸びるし、キャンバスも伸びるし、伸びることでブレるに決まってますよね。

では、iphone6は確かに横幅375pxの携帯電話ですが、それでもブレの問題があります、なぜでしょうか?モバイルのHD画面には問題があるのです。これはいわゆる2倍画面や3倍画面で、画面のDPIとも呼ばれています。HD画面では、インターフェイスを描画する際に2pxの幅を1pxとしてレンダリングするため、HD効果が発生します。つまり、HD画面で見る375pxは、実際には750ピクセルで描かれており、キャンバスは実際には375pxを750pxに引き伸ばして表示されているので、ぼやけるに決まっているのです。

さて、ぼやける原因がわかったところで、それはHD画面による問題なのですが、ではどうすればいいのでしょうか?

解決方法

2x画面なら、デザイン上の375pxのキャンバスを750pxとして描画すれば解決するのでは?

キャンバススタイルの設定

幅や高さを書く代わりに、スタイルを書く。これは画像と同じで、画像の元の幅や高さがどうであろうと、引き伸ばされていようと圧縮されていようと、画面全体に広がるようにする。スタイルで書かれた幅や高さは、画像の元の幅や高さではない、つまり、スタイルで書かれた幅や高さは、キャンバスの本当の幅や高さではないのだ

<canvas id="map" style="width: 375px;height:330px;"></canvas>

キャンバスの幅と高さを設定します

上のスタイルはキャンバスの本当の幅と高さではないので、どのように幅と高さを設定するのでしょうか?

通常画面、2倍画面、3倍画面にはそれぞれどのように適応させるのか?

<canvas id="map" style="width: 375px;height:330px;"></canvas>

<script>
let canvas = document.querySelector('#map');
// Get the screen inverted to a few times the screen.
let getPixelRatio = function(context) {
  var backingStore = context.backingStorePixelRatio ||
    context.webkitBackingStorePixelRatio ||
    context.mozBackingStorePixelRatio ||
    context.msBackingStorePixelRatio ||
    context.oBackingStorePixelRatio ||
    context.backingStorePixelRatio || 1;
   return (window.devicePixelRatio || 1) / backingStore;
};
 // iphone6 gets 2 
const pixelRatio = getPixelRatio(canvas);
// Set the real width and height of the canvas
canvas.width = pixelRatio * canvas.offsetWidth; // think of it as 2 * 375 = 750 
canvas.height = pixelRatio * canvas.offsetHeight;
</script>



すると、キャンバスの幅と高さはこのようになり、キャンバスの幅750、2倍画面ならギリギリ収まる!!!!

設定後の幅と高さ

描画開始点

例えば、375のデザインでは、半径2pxのドットがあり、ドットの位置はx:100,y:100になります。

そこで、幅750のキャンバスを用意し、幅と高さが以前の2倍になるようにしました。視覚的に同じ位置を保つには、点を x:100*pixelRatio,y:100*pixelRatio の位置に描画する必要があります。

コードの全容は以下の通りです。

<canvas id="map" style="width: 375px;height:330px;"></canvas>

<script>
let canvas = document.querySelector('#map');
// Get the screen inverted to a few times the screen.
let getPixelRatio = function(context) {
  var backingStore = context.backingStorePixelRatio ||
    context.webkitBackingStorePixelRatio ||
    context.mozBackingStorePixelRatio ||
    context.msBackingStorePixelRatio ||
    context.oBackingStorePixelRatio ||
    context.backingStorePixelRatio || 1;
   return (window.devicePixelRatio || 1) / backingStore;
};
 // iphone6 gets 2 
const pixelRatio = getPixelRatio(canvas);
// Set the real width and height of the canvas
canvas.width = pixelRatio * canvas.offsetWidth; // think of it as 2 * 375 = 750 
canvas.height = pixelRatio * canvas.offsetHeight;

// Start drawing points
let ctx = canvas.getContext("2d");
ctx.beginPath();
 // the position and size on the 375 design should be *pixelRatio because our current canvas is 750
ctx.arc(100*pixelRatio, 100*pixelRatio, 2*pixelRatio, 0, 2 * Math.PI);
ctx.fillStyle = "#fff";
ctx.fill();
ctx.closePath();

// ... The rest of your code
</script>

以上、本記事の全内容をご紹介しましたが、皆様の学習のお役に立てれば幸いです。また、Script Houseをより一層応援していただければ幸いです。