ディスプレイの表示倍率に関係なく画像を等倍表示する JavaScript

更新日: 公開日:2023/02/14
画面の表示倍率に関係なく画像を等倍表示する JavaScript

問題

4K や Retina といった高解像度のディスプレイでは、ピクセルあたりの表示倍率(スケール)が 150% や 200% になります。Web サイトに掲載した画像も同様に、1.5 倍、2倍の表示になって画像がぼやけるので、拡大表示させたくない。

ディスプレイの表示倍率を無視して、画像を出力する方法はあるか?

解決方法

JavaScript で、ディスプレイの表示スケール devicePixelRatio が取得できます。1ピクセルあたり何倍に拡大して表示しているのかを表した値です。例えば 150% であれば 1.5、100% なら 1.0 です。

この devicePixelRatio を使って img タグの画像が等倍になるように width を計算して設定すれば、ブラウザの表示が拡大されてもぼやけず、常に Dot by Dot で画像を表示できます。

Index

ディスプレイの表示スケールを無視する JavaScript

  1. img タグには width と height を設定【必須】
  2. 等倍表示する img タグに class 属性を設定
  3. img タグの CSS に height: auto; を設定
  4. HTML 読み込み時に JavaScript で等倍処理を実行
  5. 複数画像あっても問題なく処理できるようにする

プログラム実装例 HTML と CSS

HTML
<img src="(画像のURL)" class="equal-size" width="900" height="600" alt="テスト画像" >
CSS
img.equal-size {
  height: auto;
}

例として 900 × 600 の画像を用意します。WordPress で挿入すれば勝手に width と height が設定されるので、クラスだけ追加すれば OK です。クラス名はわかりやすく equal-size と命名しておきます。

width 設定は必須です。なぜなら naturalwidth が取得できない状況があるため。

Chrome など昨今のモダンブラウザは、スクロールに応じて画像を遅延読み込みする Lazy Load 機能を持っています。naturalwidth は画像読み込みが完了してからでないと取得できない情報です。つまり JavaScript の処理時に画像が読み込まれていないと、値が 0 で返却されます。

これでは計算元となる画像サイズがわからないため、予めタグ内に width を指定する必要があるのです。

プログラム実装例 JavaScript

やることは簡単で、元の画像の width をディスプレイの表示倍率で割ったものを設定するだけ。高さは css の auto 設定により、横幅だけ縮小しても最適なサイズが指定されます。

JavaScript
<script>
// DOM 読み込み後に処理実行
document.addEventListener("DOMContentLoaded", function() {
  let $k = 0;

  // スケールの倍率を取得
  let dpr = window.devicePixelRatio;
  // 縮小する画像の要素を取得
  let eqsize = document.getElementsByClassName('equal-size');
  // 画像が小さくなりすぎるのを防ぐための対策
  if ( dpr > 1.5 ) dpr = 1.5;

  // width をスケール倍率で割ったものを再設定
  while ( $k < eqsize.length) {
    // width 属性の設定忘れ対策
    if ( eqsize[$k].getAttribute('width') != null ) {
      eqsize[$k].style.width = eqsize[$k].getAttribute('width') / dpr + 'px';
    }
    $k++;
  }
});
</script>

ポイントは11行目。全て Dot by Dot の等倍表示にすると、スマホでの表示が小さくなりすぎます。そのためスケールが 1.5 倍より大きい場合は、等倍表示させていません。もし全てのケースで等倍表示したければ、11行目を消してください。(もしくは値を書き換えて倍率を調節)

例えば iPhone 14 の Pixel Ratio は3倍です。横幅表示は 390px で、実際のピクセル数は 1170px。画素密度が 460ppi と細かく、Dot by Dot 表示でなくても画像は綺麗に見えるます。そこまで大きな倍率は、考慮しなくて良いと思います。

サンプル例のように 1.5 倍で留めておくか、Ratina ディスプレイの2倍まで対応しておくか、実際に試してみてください。

プログラムの実行結果を比較

1枚目の画像は、等倍処理のプログラムが動かないように equal-size のクラスを設定していないもの。2枚目の画像は、クラス設定して等倍表示したもの。

テスト画像 函館の路面電車

テスト画像 函館の路面電車

上の画像は引き伸ばしたような、ぼやけた画像になっています。一方、下の画像は小さく表示されていますが、鮮明に描画されているのがわかります。

もし2枚の画像が同じ大きさで見えているなら、今使っているディスプレイの表示倍率は 100% です。例えばフルハイビジョンのモニターがそれに該当します。ノートパソコンや 4K ディスプレイで表示すれば、表示倍率 150% ~ 200% に設定されているので、違いがわかると思います。

あなたが見ているディスプレイの表示倍率は です。

ちなみに Windows であれば、ディスプレイの設定画面にある [拡大/縮小] の項目から表示倍率が確認できます。僕の環境は 32 インチの 4K モニターなので、倍率が 150% になっています。

Windows 11 のディスプレイ表示倍率を確認する方法

以上、ディスプレイの表示倍率に関係なく画像を等倍表示する JavaScript の紹介でした。

\ この記事をシェアする /

このブログの運営者

NJ

Web系メインで従事していた元システムエンジニア。現在は個人事業主として独立。Webサイト運営における「困った問題」の解決方法をブログで発信。Web サイト運営、ポップデザインや動画制作など、パソコンでモノづくりをしている。