HTML5キャンバス100%幅ビューポートの高さ?


151

ビューポートの幅と高さの100%を占めるキャンバス要素を作成しようとしています。

あなたは私の例で見ることができ、ここでしかし、それはChromeとFirefoxの両方にスクロールバーを追加して、発生しています。余分なスクロールバーを防ぎ、ウィンドウの幅と高さをキャンバスのサイズに正確に指定するにはどうすればよいですか?



かなり面白いFonejackerコメディスケッチを思い出させます:youtu.be/6oj_oLMD688
フランシスブース

回答:


260

キャンバスを常に全画面の幅と高さにするには、つまりブラウザのサイズが変更された場合でも、キャンバスをwindow.innerHeightとwindow.innerWidthにサイズ変更する関数内で描画ループを実行する必要があります。

例:http//jsfiddle.net/jaredwilli/qFuDr/

HTML

<canvas id="canvas"></canvas>

JavaScript

(function() {
    var canvas = document.getElementById('canvas'),
            context = canvas.getContext('2d');

    // resize the canvas to fill browser window dynamically
    window.addEventListener('resize', resizeCanvas, false);

    function resizeCanvas() {
            canvas.width = window.innerWidth;
            canvas.height = window.innerHeight;

            /**
             * Your drawings need to be inside this function otherwise they will be reset when 
             * you resize the browser window and the canvas goes will be cleared.
             */
            drawStuff(); 
    }
    resizeCanvas();

    function drawStuff() {
            // do your drawing stuff here
    }
})();

CSS

* { margin:0; padding:0; } /* to remove the top and left whitespace */

html, body { width:100%; height:100%; } /* just to be sure these are full screen*/

canvas { display:block; } /* To remove the scrollbars */

これが、キャンバスをブラウザの幅と高さ全体に適切に作成する方法です。drawStuff()関数で、キャンバスに描画するためのすべてのコードを配置する必要があります。


2
パディングを削除し、幅、高さを100%に設定する必要があるのはなぜですか?
コス

3
これは主に、ブラウザのデフォルトのユーザースタイルシートを上書きするためのものだと思います。ある種の正規化またはリセットcssファイルを使用している場合、これはすでに処理されているため、これは必要ありません。
jaredwilli 2013年

2
かなりのサイズ変更が予想される場合。たとえば、縦向き/横向きのデバイスでdebounceは、サイズを変更する必要があります。そうしないと、ブラウザがいっぱいになります。
dooburt 2014

24
display: block:これにより、スクロールバーが削除されるだけでなく、通常はブロック内のテキスト行の下に追加されるドキュメント本文の高さから2pxが削除されます。したがって、そのための+1
Neptilo 2014

2
プラスノーjQueryのための1
フェリックス・ガニオン-グルニエ

27

ビューポートユニット(CSS3)を試すことができます。

canvas { 
  height: 100vh; 
  width: 100vw; 
  display: block;
}

5
追加するdisplay: block;と、それが仕事をします。
superlukas 2014

18
これを試してみたところ、ChromeとFirefoxでは、キャンバスに画像がフルビューポートに引き伸ばされて表示されていることがわかりました。新しく描かれた要素も引き伸ばされます。
ビビアン川

8
@Danielは正しいです-この答えは間違っています。キャンバスコンテキストの内部寸法ではなく、DOM要素の寸法を設定します。違いについては、関連する質問に対する私の回答を参照しください。
ダンダスカレスク2015

19
この方法は機能せず、テキストを引き伸ばします。残念ながら、 JSを使用する必要 があります。
i336_ 2016年

ストレッチしたい場合があります(つまり、プログレスバー)。ありがとう、私の場合は素晴らしいです!
Andrew McOlash

16

ウィンドウのサイズ変更時にキャンバスのサイズを動的に適応させる方法についてのより一般的な質問に答えます。受け入れられた答えは、幅と高さが両方とも100%であると想定されている場合を適切に処理します。これは、求められたものですが、キャンバスのアスペクト比も変更します。多くのユーザーは、アスペクト比を変更せずに、ウィンドウのサイズ変更時にキャンバスのサイズを変更することを望んでいます。これは正確な質問ではありませんが、質問をもう少し一般的なコンテキストに置くだけで「適合」します。

ウィンドウにはアスペクト比(幅/高さ)があり、キャンバスオブジェクトも同様です。これらの2つのアスペクト比を互いにどのように関連付けるかは、明確にする必要がある1つのことです。その質問に対する「万能」の答えはありません。私は、あなたが考えていることのいくつかの一般的なケースについて説明します。欲しいです。

明確にする必要がある最も重要なこと:htmlキャンバスオブジェクトにはwidth属性とheight属性があります。次に、同じオブジェクトのcssにもwidth属性とheight属性があります。これらの2つの幅と高さは異なり、どちらもさまざまな用途に役立ちます。

幅と高さの属性を変更することは、キャンバスのサイズをいつでも変更できる1つの方法ですが、すべてを再描画する必要があります。これには時間がかかり、サイズをある程度変更できるため、必ずしも必要ではありません。 css属性を介して、この場合、キャンバスを再描画しません。

ウィンドウのサイズ変更で発生する可能性のある4つのケースがあります(すべてフルスクリーンキャンバスから始まります)

1:幅を100%のままにし、アスペクト比をそのままにします。その場合、キャンバスを再描画する必要はありません。ウィンドウサイズ変更ハンドラーも必要ありません。あなたに必要なのは

$(ctx.canvas).css("width", "100%");

ここで、ctxはキャンバスコンテキストです。フィドル:resizeByWidth

2:幅と高さの両方を100%に保ち、結果として生じるアスペクト比の変化に、引き伸ばされた画像の効果を持たせたい。これで、キャンバスを再描画する必要はありませんが、ウィンドウサイズ変更ハンドラーが必要です。ハンドラーでは、

$(ctx.canvas).css("height", window.innerHeight);

フィドル:messWithAspectratio

3:幅と高さの両方を100%に保ちたいが、アスペクト比の変化に対する答えは、画像を引き伸ばすこととは異なります。次に、再描画する必要があり、受け入れられた回答に概説されている方法でそれを行います。

フィドル:再描画

4:ページの読み込み時に幅と高さを100%にしますが、その後は一定に保ちます(ウィンドウのサイズ変更には反応しません)。

フィドル:修正

モードが設定されている63行目を除いて、すべてのフィドルのコードは同じです。フィドルコードをコピーしてローカルマシンで実行することもできます。その場合、クエリ文字列引数を使用して、?mode = redrawとしてモードを選択できます。


1
fyi:$(ctx.canvas).css("width", "100%");と同等です$(canvas).css("width", "100%"); (コンテキストのキャンバスは単なるキャンバスです)
Brad Kent

@BradKentは、実行したい「canvas-things」を実行するヘルパー関数を呼び出すときに、引数として1)キャンバスオブジェクトを渡す、2)キャンバスコンテキストを渡す、3)両方を行うことができます。私は3)が好きではなく、それctx.canvasよりもずっと短いので、canvas.getContext('2d')2)をします。したがって、canvasという変数はありませんが、ctx.canvasはあります。それがctx.canvasの由来です。
mathheadinclouds

9

http://jsfiddle.net/mqFdk/10/

<!DOCTYPE html>
<html>
<head>
    <title>aj</title>
</head>
<body>

    <canvas id="c"></canvas>

</body>
</html>

CSSを使用

body { 
       margin: 0; 
       padding: 0
     }
#c { 
     position: absolute; 
     width: 100%; 
     height: 100%; 
     overflow: hidden
   }

これは機能しますが、幅と高さが定義されていないキャンバスが残ります。キャンバスの幅と高さは、私が信じる要素で定義する必要があります。
aherrick 2010年

@aherrick:いいえ、canvas要素を機能させるために明示的な幅/高さを設定する必要はありません。このコードは正常に機能するはずです。
Jon Adams

19
実際にはそうです、キャンバス要素には明示的な幅/高さのセットが必要です。それがないと、デフォルトでブラウザのプリセット(Chromeでは300x150pxだと思います)サイズになります。キャンバスへのすべての描画はこのサイズで解釈され、ビューポートサイズの100%に拡大縮小されます。キャンバスに何かを描い、私が何を意味するのかを確認してください。歪んでしまいます。
マークカーン

キャンバスの幅と高さを100%にしようとしているのであれば、それはまったく問題ではありません。とにかくサイズを変更するだけです
jaredwilli 2012年

2
キャンバス要素の固有の寸法は、座標空間のサイズに等しく、数値はCSSピクセルで解釈されます。ただし、要素はスタイルシートによって任意のサイズにすることができます。レンダリング中に、画像はこのレイアウトサイズに合うように拡大縮小されます。
jaredwilli 2012年

9

私もこの質問に対する答えを探していましたが、受け入れられた答えは私にとって壊れていました。どうやらwindow.innerWidthの使用は移植性がありません。一部のブラウザでは動作しますが、Firefoxが気に入らないことに気づきました。

Gregg Tavaresは、この問題に直接対処する優れたリソースをここに投稿しました:http//webglfundamentals.org/webgl/lessons/webgl-anti-patterns.html (アンチパターン#の3と4を参照)。

window.innerWidthの代わりにcanvas.clientWidthを使用すると、うまく機能するようです。

グレッグが提案するレンダリングループは次のとおりです。

function resize() {
  var width = gl.canvas.clientWidth;
  var height = gl.canvas.clientHeight;
  if (gl.canvas.width != width ||
      gl.canvas.height != height) {
     gl.canvas.width = width;
     gl.canvas.height = height;
     return true;
  }
  return false;
}

var needToRender = true;  // draw at least once
function checkRender() {
   if (resize() || needToRender) {
     needToRender = false;
     drawStuff();
   }
   requestAnimationFrame(checkRender);
}
checkRender();

2

(動靜能量の答えを拡張する)

体を埋めるようにキャンバスのスタイルを設定します。キャンバスにレンダリングするときは、そのサイズを考慮に入れてください。

http://jsfiddle.net/mqFdk/356/

<!DOCTYPE html>
<html>
<head>
    <title>aj</title>
</head>
<body>

    <canvas id="c"></canvas>

</body>
</html>

CSS:

body { 
       margin: 0; 
       padding: 0
     }
#c { 
     position: absolute; 
     width: 100%; 
     height: 100%; 
     overflow: hidden
   }

Javascript:

function redraw() {
    var cc = c.getContext("2d");
    c.width = c.clientWidth;
    c.height = c.clientHeight;
    cc.scale(c.width, c.height);

    // Draw a circle filling the canvas.
    cc.beginPath();
    cc.arc(0.5, 0.5, .5, 0, 2*Math.PI);
    cc.fill();
}

// update on any window size change.
window.addEventListener("resize", redraw);

// first draw
redraw();

1

携帯電話の場合は、それを使用することをお勧めします

canvas.width = document.documentElement.clientWidth;
canvas.height = document.documentElement.clientHeight;

向きを変更すると正しく表示されないためです。向きを縦向きに変更すると、「ビューポート」が増加します。完全な 例を参照してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.