ディスプレイの表示倍率に関係なく画像を等倍表示する JavaScript
問題
4K や Retina といった高解像度のディスプレイでは、ピクセルあたりの表示倍率(スケール)が 150% や 200% になります。Web サイトに掲載した画像も同様に、1.5 倍、2倍の表示になって画像がぼやけるので、拡大表示させたくない。
ディスプレイの表示倍率を無視して、画像を出力する方法はあるか?
解決方法
JavaScript で、ディスプレイの表示スケール devicePixelRatio が取得できます。1ピクセルあたり何倍に拡大して表示しているのかを表した値です。例えば 150% であれば 1.5、100% なら 1.0 です。
この devicePixelRatio を使って img タグの画像が等倍になるように width を計算して設定すれば、ブラウザの表示が拡大されてもぼやけず、常に Dot by Dot で画像を表示できます。
ディスプレイの表示スケールを無視する JavaScript
- img タグには width と height を設定【必須】
- 等倍表示する img タグに class 属性を設定
- img タグの CSS に height: auto; を設定
- HTML 読み込み時に JavaScript で等倍処理を実行
- 複数画像あっても問題なく処理できるようにする
プログラム実装例 HTML と CSS
<img src="(画像のURL)" class="equal-size" width="900" height="600" alt="テスト画像" >
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 設定により、横幅だけ縮小しても最適なサイズが指定されます。
<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% になっています。
以上、ディスプレイの表示倍率に関係なく画像を等倍表示する JavaScript の紹介でした。