HTML5 Canvas 100% Breite Höhe des Ansichtsfensters?

151

Ich versuche, ein Canvas-Element zu erstellen, das 100% der Breite und Höhe des Ansichtsfensters einnimmt.

Sie können in meinem Beispiel hier sehen, dass dies geschieht, jedoch werden Bildlaufleisten sowohl in Chrome als auch in FireFox hinzugefügt. Wie kann ich die zusätzlichen Bildlaufleisten verhindern und genau die Breite und Höhe des Fensters angeben, die der Größe der Leinwand entspricht?

aherrick
quelle
1
Siehe auch: stackoverflow.com/questions/4037212
Hippietrail
Erinnert mich an eine ziemlich amüsante Fonejacker-Comedy-Skizze: youtu.be/6oj_oLMD688?t=22s
Francis Booth

Antworten:

257

Damit die Leinwand immer die volle Breite und Höhe des Bildschirms erreicht, dh auch wenn die Größe des Browsers geändert wird, müssen Sie Ihre Zeichenschleife in einer Funktion ausführen, die die Größe der Leinwand auf window.innerHeight und window.innerWidth ändert.

Beispiel: 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 */

Auf diese Weise können Sie die Leinwand in voller Breite und Höhe des Browsers richtig gestalten. Sie müssen nur den gesamten Code zum Zeichnen in die Zeichenfläche in der Funktion drawStuff () einfügen.

jaredwilli
quelle
2
Warum muss die Polsterung entfernt und Breite und Höhe auf 100% eingestellt werden?
Kos
3
Ich glaube, es dient hauptsächlich dazu, das Benutzer-Stylesheet zu überschreiben, für das der Browser Standardeinstellungen hat. Wenn Sie eine Art CSS-Datei zum Normalisieren oder Zurücksetzen verwenden, ist dies nicht erforderlich, da dies bereits erledigt ist.
Jaredwilli
2
Wenn Sie ziemlich viel Größenänderung erwarten; Auf einem Hoch- / Querformatgerät möchten Sie beispielsweise debouncedie Größe ändern, da sonst der Browser überflutet wird.
Dooburt
24
display: block: Dadurch werden nicht nur Bildlaufleisten entfernt, sondern auch 2 Pixel aus der Höhe des Dokumentenkörpers entfernt, die normalerweise unter Textzeilen innerhalb eines Blocks hinzugefügt werden. Also +1 dafür
Neptilo
2
plus eins für kein jQuery
Félix Gagnon-Grenier
26

Sie können Ansichtsfenstereinheiten (CSS3) ausprobieren :

canvas { 
  height: 100vh; 
  width: 100vw; 
  display: block;
}
Vitalii Fedorenko
quelle
5
Hinzufügen display: block;und es macht den Job.
Superlukas
18
Ich habe dies versucht und festgestellt, dass in Chrome und Firefox auf der Leinwand einfach das Bild angezeigt wird, das bis zum vollständigen Ansichtsfenster gestreckt ist. Auch neu gezeichnete Elemente werden gedehnt.
Vivian River
8
@ Daniel ist richtig - diese Antwort ist falsch . Es wird nicht die interne Dimension des Canvas-Kontexts festgelegt, sondern die Dimensionen des DOM-Elements. Für den Unterschied siehe meine Antwort auf eine verwandte Frage .
Dan Dascalescu
19
Diese Methode funktioniert nicht, sie streckt den Text. Sie leider haben JS zu verwenden.
i336_
16

Ich beantworte die allgemeinere Frage, wie sich die Größe einer Leinwand beim Ändern der Fenstergröße dynamisch anpassen lässt. Die akzeptierte Antwort behandelt den Fall angemessen, in dem sowohl Breite als auch Höhe 100% betragen sollen, was verlangt wurde, aber auch das Seitenverhältnis der Leinwand ändert. Viele Benutzer möchten, dass die Größe der Leinwand beim Ändern der Fenstergröße geändert wird, wobei das Seitenverhältnis jedoch unberührt bleibt. Es ist nicht die genaue Frage, aber es "passt", nur um die Frage in einen etwas allgemeineren Kontext zu stellen.

Das Fenster hat ein gewisses Seitenverhältnis (Breite / Höhe), ebenso wie das Canvas-Objekt. Wie Sie möchten, dass sich diese beiden Seitenverhältnisse zueinander verhalten, ist eine Sache, über die Sie sich klar sein müssen. Es gibt keine Antwort auf diese Frage "Eine Größe passt für alle" - ich werde einige häufige Fälle von dem durchgehen, was Sie könnten wollen.

Das Wichtigste, worüber Sie sich im Klaren sein müssen: Das HTML-Canvas-Objekt verfügt über ein width-Attribut und ein height-Attribut. und dann hat das CSS desselben Objekts auch ein Attribut width und height. Diese beiden Breiten und Höhen sind unterschiedlich, beide sind für verschiedene Dinge nützlich.

Das Ändern der Attribute für Breite und Höhe ist eine Methode, mit der Sie jederzeit die Größe Ihrer Leinwand ändern können. Dann müssen Sie jedoch alles neu streichen. Dies ist zeitaufwändig und nicht immer erforderlich, da Sie einige Größenänderungen vornehmen können In diesem Fall zeichnen Sie die Zeichenfläche nicht neu.

Ich sehe 4 Fälle, in denen Sie möglicherweise die Fenstergröße ändern möchten (alle beginnen mit einer Vollbild-Leinwand).

1: Sie möchten, dass die Breite 100% bleibt und das Seitenverhältnis unverändert bleibt. In diesem Fall müssen Sie die Leinwand nicht neu zeichnen. Sie benötigen nicht einmal einen Handler zur Größenänderung von Fenstern. Alles was Sie brauchen ist

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

Dabei ist ctx Ihr Canvas-Kontext. Geige: resizeByWidth

2: Sie möchten, dass sowohl Breite als auch Höhe 100% bleiben, und Sie möchten, dass die resultierende Änderung des Seitenverhältnisses den Effekt eines gestreckten Bildes hat. Jetzt müssen Sie die Leinwand immer noch nicht neu zeichnen, aber Sie benötigen einen Fensteränderungs-Handler. Im Handler tun Sie das

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

Geige: messWithAspectratio

3: Sie möchten, dass sowohl Breite als auch Höhe 100% bleiben, aber die Antwort auf die Änderung des Seitenverhältnisses unterscheidet sich von der Dehnung des Bildes. Dann müssen Sie neu zeichnen und es so machen, wie es in der akzeptierten Antwort beschrieben ist.

Geige: neu zeichnen

4: Sie möchten, dass Breite und Höhe beim Laden der Seite 100% betragen, danach jedoch konstant bleiben (keine Reaktion auf die Größenänderung des Fensters.

Geige: behoben

Alle Geigen haben den gleichen Code, mit Ausnahme der Zeile 63, in der der Modus eingestellt ist. Sie können auch den Geigencode kopieren, der auf Ihrem lokalen Computer ausgeführt werden soll. In diesem Fall können Sie den Modus über ein Querystring-Argument als? Mode = redraw auswählen

Mathheadinclouds
quelle
1
fyi: $(ctx.canvas).css("width", "100%");ist äquivalent zu $(canvas).css("width", "100%"); (die Leinwand des Kontexts ist nur die Leinwand)
Brad Kent
@BradKent Wenn Sie eine Hilfsfunktion aufrufen, die die gewünschten "Canvas-Dinge" ausführt, können Sie entweder als Argument (e) 1) das Canvas-Objekt übergeben, 2) den Canvas-Kontext übergeben, 3) beide. Ich mag 3) nicht und ctx.canvasist viel kürzer als canvas.getContext('2d')- deshalb mache ich 2). Daher gibt es keine Variable namens canvas, aber ctx.canvas. Von dort kommt ctx.canvas.
Mathheadinclouds
9

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

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

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

</body>
</html>

mit CSS

body { 
       margin: 0; 
       padding: 0
     }
#c { 
     position: absolute; 
     width: 100%; 
     height: 100%; 
     overflow: hidden
   }
Unpolarität
quelle
Das funktioniert, aber meine Leinwand bleibt ohne definierte Breite und Höhe. Die Leinwandbreite und -höhe muss auf dem Element definiert werden, von dem ich glaube.
aherrick
@aherrick: Nein, für das Canvas-Element muss keine explizite Breite / Höhe festgelegt sein, damit es funktioniert. Dieser Code sollte gut funktionieren.
Jon Adams
18
Ja, Canvas-Elemente benötigen eine explizite Breite / Höhe. Ohne sie haben sie standardmäßig eine voreingestellte Browsergröße (in Chrome, glaube ich, 300x150px). Alle Zeichnungen auf der Leinwand werden in dieser Größe interpretiert und dann auf 100% der Größe des Ansichtsfensters skaliert. Versuchen Sie, etwas auf Ihre Leinwand zu zeichnen , um zu sehen, was ich meine - es wird verzerrt.
Mark Kahn
Wenn Sie versuchen, die Leinwand zu 100% breit und hoch zu machen, spielt das überhaupt keine Rolle. Sie ändern es einfach trotzdem
jaredwilli
1
Die intrinsischen Abmessungen des Canvas-Elements entsprechen der Größe des Koordinatenraums, wobei die Zahlen in CSS-Pixeln interpretiert werden. Das Element kann jedoch durch ein Stylesheet beliebig dimensioniert werden. Während des Renderns wird das Bild auf diese Layoutgröße skaliert.
Jaredwilli
8

Ich suchte auch nach einer Antwort auf diese Frage, aber die akzeptierte Antwort brach für mich. Anscheinend ist die Verwendung von window.innerWidth nicht portabel. Es funktioniert in einigen Browsern, aber ich habe festgestellt, dass es Firefox nicht gefallen hat.

Gregg Tavares hat hier eine großartige Ressource veröffentlicht, die dieses Problem direkt anspricht: http://webglfundamentals.org/webgl/lessons/webgl-anti-patterns.html (Siehe Anti-Pattern # 3 und 4).

Die Verwendung von canvas.clientWidth anstelle von window.innerWidth scheint gut zu funktionieren.

Hier ist Greggs vorgeschlagene Render-Schleife:

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();
David
quelle
2

(Erweiterung der Antwort von 動靜 能量)

Gestalte die Leinwand, um den Körper zu füllen. Berücksichtigen Sie beim Rendern auf der Leinwand die Größe.

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();
Vincent Scheib
quelle
1

Für Handys ist es besser, es zu benutzen

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

da es nach dem Ändern der Ausrichtung falsch angezeigt wird. Das „Ansichtsfenster“ wird vergrößert, wenn die Ausrichtung auf Hochformat geändert wird. Siehe vollständiges Beispiel

Dzanis
quelle