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

高解像度画面でのキャンバスブラーの問題を記憶する

2022-01-14 14:26:20

プリアンブル

最近、あるプロジェクトを進めていたところ、会社のパソコンでは問題なかったのですが、自分のパソコンでは問題が発生しました。キャンバスのプロジェクトで作業をしていたのですが、自分のパソコンで実行したところ、クリックが選択されないという問題と、キャンバスのリフレッシュにゴーストが発生するという問題が発生したのです。まず、この2つの問題は、canvas要素のボーダーの問題が原因であることは間違いないのですが、コードからは、問題がないので、画面に関係しているのかどうか、やはり、canvasの問題の中には、本当に画面に関係しているものや、ハードウェアのグラフィックカードに関係しているものまでありますね。

devicePixelRatio プロパティ

案の定、devicePixelRatioという1つのプロパティが異なっていることが判明しました。
そこで、この属性の意味をよく見てみると、mdnで次のように説明されている。

このプロパティは、現在の表示デバイスの物理的なピクセル解像度と CSS ピクセル解像度の比率を返すものである。この値は、ピクセルサイズの比率、つまり、物理的なピクセルのサイズに対する CSS ピクセルのサイズの比率と解釈することもできる。

会社のデスクトップはdevicePixelRatioが1、自分のパソコンは1.25。自分のパソコンはHD画面だから、HD画面ってなんだろう?
HDディスプレイの原理は以下の通りです。

  1. 超高画素密度の液晶ディスプレイ
  2. 同じ大きさの画面に表示される画素数が1ではなく、複数の画素数

すると、HD画面上の1ピクセル点がdevicePixelRatioピクセルになるので、canvasキャンバスもその効果を受け、HD画面上の同じ画像は大きくなりますが、画像が拡大縮小してブレが発生するので、実際のキャンバスサイズは大きくならないことがわかります。

キャンバスの幅と高さ vs. CSS の幅と高さ

では、キャンバスの高解像度化問題はどのように解決すればよいのでしょうか。高解像度画面ではキャンバスのピクセルポイントが多くなり、キャンバスが拡大縮小されるため、どうにかしてキャンバスを縮小することはできないのでしょうか?答えは「イエス」です。
まずは、キャンバスのピクセルを知ることからはじめましょう。テキストを描こう

<canvas id="canvas1" width="300" height="150"></canvas>
....


ctx1.beginPath();
ctx1.font = '20px arial';
ctx1.fillText('Html5 canvas', 50, 50);

これにより、以下のようになります。

キャンバスを作成していますが、今回はcssでキャンバスの幅と高さを設定しています。

<canvas id="canvas2" style="width: 200px; height: 200px"></canvas>
.....



ctx2.beginPath();
ctx2.font = '20px arial';
ctx2.fillText('Html5 canvas', 50, 50);



今度は次のような効果が得られます。

キャンバス上の文字が大幅に縮小されているのがよくわかりますが、これはなぜでしょうか。canvas は画像を描画するものであり、canvas を使用して画像を描画した後、まず canvas の幅と高さに基づく画像を生成し、それを dom ツリーを通じて css でレンダリングするため、canvas の幅と高さが実際の画像の幅と高さになり、css の幅と高さがレンダリング画像の実際の大きさになる、とこのように理解することができます。このプロパティは、デバイスの物理的なピクセル解像度と CSS ピクセル解像度の比率を返します。私たちのキャンバスは、画像が大きくなる原因であるHD画面のデバイスのために絵を描画し、しかし、ブラウザのレンダリングウィンドウは大きくならないので、画像は、高精細画面のピクセルポイントが多くなるように、キャンバスがぼやけ、結果として大きな画像になるように縮小表示されます。その後、我々はキャンバスの幅と高さをdevicePixelRatio倍に設定することにより、キャンバスのサイズを設定することができますし、キャンバスのスケーリング比をdevicePixelRatio倍に設定し、維持し、キャンバス等倍拡大、次にこの方法は、我々が描くことに相当する 我々は絵を描くとき、我々は大きくなるように画像を拡大縮小し、CSSレンダリングを介して、我々は再びそれを縮小する、そうキャンバスサイズは歪まないでしょう。コードは以下の通り。

function makeHighRes(canvas) {
    var ctx = canvas.getContext('2d');
    // Get the device pixel ratio, falling back to 1.               
    var dpr = window.devicePixelRatio || window.webkitDevicePixelRatio || window.mozDevicePixelRatio || 1;

    // Get the size of the canvas in CSS pixels.
    var oldWidth = canvas.width;
    var oldHeight = canvas.height;
    // Give the canvas pixel dimensions of their CSS
    // size * the device pixel ratio.
    canvas.width = Math.round(oldWidth * dpr);
    width = Math.round(oldWidth * dpr); canvas.height = Math.round(oldHeight * dpr);
    canvas.style.width = oldWidth + 'px';
    canvas.style.height = oldHeight + 'px';
    // Scale all drawing operations by the dpr, so you
    // don't have to worry about the difference.
    ctx.scale(dpr, dpr);
    return ctx;
}



ところで、ウェブ上にはbackingStoreRatio属性を使用した古いソリューションがありますが、これは非推奨です!
また、このライブラリ hidpi-canvas-polyfill も使えます。このライブラリも canvas の描画ビューを変更するために我々のメソッドを使用しますが、すべての canvas 描画 api を対応する devicePixelRatio 倍でスケールしており、非常によく考えられています。

参考リンク
https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/HTML-canvas-guide/SettingUptheCanvas/ SettingUptheCanvas.html
https://developer.mozilla.org/zh-CN/docs/Web/API/Window/devicePixelRatio
https://www.jianshu.com/p/2cd5143cf9aa

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