実現したいことは
「canvas要素のサイズをブラウザの表示領域のデバイスピクセルにできるだけ一致させたい(擬似的な1:1全画面表示)」
というだけの単純な話なのですが、
「viewportのwidthを設定した場合」「回転・リサイズした場合」
の適切な設定方法がわかりません。
下記コードだと、例えばdevicePixelRatioが2、短辺のCSSピクセルが375pxのiPhoneの場合、
初回の(1)部分の実行でviewportのwidthをデバイスピクセルの750に設定すると、
回転時(リサイズ時)の(2)ではwindow.innerWidthが上述で設定した750の値で取得されるため、
以降リサイズのたびに倍々に増えていってしまいます。
(なおiPhoneのSafariではviewportの最大値がCSSピクセルの4倍までに制限されているようで、倍々が途中で打ち止めになります)
かといって(1)をフラグなどで一度しか発火しないようにすると、当然ですが初回で設定した横幅に固定されてしまいます。
いかなる場合においても(すなわちviewportの設定などに依存せず)CSSピクセルまたはデバイスピクセルを取得できる関数などはないのでしょうか。
よく使われそうな機能なのに調べても同様の記事等を見かけないので、何か単純なことを見落としているのかもしれません。
(なお算出されるCSSピクセルやデバイスピクセルが、実媒体との厳密な一致でなく近似であることは理解しています。
またアドレスバーなどのサイズについては今回の検討に含みません)
ご教示ください。
html
1<!DOCTYPE html> 2<html> 3 4<head> 5 <meta name='viewport' content="width=device-width"> 6</head> 7 8<body style="background-color:skyblue;margin:0;"> 9 <canvas id="maincanvas" style="background-color:pink;"></canvas> 10</body> 11 12<script> 13 const Resize = () => { 14 const canvas = document.getElementById('maincanvas'); 15 let w = window.innerWidth; // <-(2) 16 let h = window.innerHeight; 17 if (window.devicePixelRatio > 1) { // <-(1) 18 w = w * window.devicePixelRatio; 19 h = h * window.devicePixelRatio; 20 document.querySelector("meta[name='viewport']").setAttribute('content', `width=${w}`); 21 } 22 canvas.width = w; 23 canvas.height = h; 24 // 下記は確認表示用 25 console.log(`rotate = ${window.innerWidth > window.innerHeight ? 'landscape' : 'portrait'}`); 26 console.log(` window.iW = ${window.innerWidth}, window.iH = ${window.innerHeight}`); 27 console.log(` canvas.w = ${canvas.width}, canvas.h = ${canvas.height}`); 28 canvas.getContext('2d').font = `normal 48px sans-serif`; 29 canvas.getContext('2d').fillText(`rotate = ${window.innerWidth > window.innerHeight ? 'landscape' : 'portrait'}`, 0, 100); 30 canvas.getContext('2d').fillText(` window.iW = ${window.innerWidth}, window.iH = ${window.innerHeight}`, 0, 200); 31 canvas.getContext('2d').fillText(` canvas.w = ${canvas.width}, canvas.h = ${canvas.height}`, 0, 300); 32 }; 33 window.addEventListener('resize', Resize); 34 Resize(); 35</script> 36 37</html>