HTML5 Canvas Altezza 100% della larghezza della finestra?


151

Sto cercando di creare un elemento canvas che occupa il 100% della larghezza e dell'altezza del viewport.

Puoi vedere nel mio esempio qui che si sta verificando, tuttavia sta aggiungendo barre di scorrimento in Chrome e FireFox. Come posso evitare le barre di scorrimento extra e fornire esattamente la larghezza e l'altezza della finestra in modo che siano le dimensioni della tela?



Mi ricorda uno schizzo comico piuttosto divertente di Fonejacker: youtu.be/6oj_oLMD688?t=22s
Francis Booth,

Risposte:


258

Per rendere sempre la larghezza e l'altezza dello schermo a schermo intero, il che significa anche quando il browser viene ridimensionato, è necessario eseguire il ciclo di disegno all'interno di una funzione che ridimensiona l'area di disegno su window.innerHeight e window.innerWidth.

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

Ecco come rendere correttamente la larghezza della tela e l'altezza del browser. Devi solo mettere tutto il codice per disegnare sulla tela nella funzione drawStuff ().


2
Perché è necessario rimuovere l'imbottitura e impostare larghezza, altezza al 100%?
Kos,

3
Credo che sia principalmente per sovrascrivere il foglio di stile dell'utente per cui il browser ha le impostazioni predefinite. Se stai usando un tipo di file CSS normalizzato o ripristinato, questo non è necessario poiché sarà già curato.
jaredwilli,

2
Se ti aspetti un bel ridimensionamento; su un dispositivo verticale / orizzontale, ad esempio, vorresti debounceridimensionare, altrimenti inonderai il browser.
dooburt

24
display: block: Non solo rimuove le barre di scorrimento, ma rimuove 2px dall'altezza del corpo del documento, che normalmente vengono aggiunte sotto le righe di testo all'interno di un blocco. Quindi +1 per quello
Neptilo il

2
più uno per nessun jQuery
Félix Gagnon-Grenier,

26

Puoi provare le unità viewport (CSS3):

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

5
Aggiungi display: block;e fa il lavoro.
superlukas,

18
Ho provato questo e ho scoperto che in Chrome e Firefox, l'area di disegno mostra semplicemente l'immagine estesa a tutto il viewport. Anche gli elementi appena disegnati vengono allungati.
Fiume Vivian,

8
@Daniel ha ragione: questa risposta è sbagliata . Non imposterà la dimensione interna del contesto della tela, ma piuttosto le dimensioni dell'elemento DOM. Per la differenza, vedi la mia risposta a una domanda correlata .
Dan Dascalescu,

19
Questo metodo non funziona, allunga il testo. È purtroppo necessario utilizzare JS.
i336_

16

Risponderò alla domanda più generale su come fare in modo che una tela si adatti dinamicamente alle dimensioni al ridimensionamento della finestra. La risposta accettata gestisce in modo appropriato il caso in cui sia la larghezza che l'altezza dovrebbero essere al 100%, il che è ciò che è stato richiesto, ma che cambierà anche le proporzioni della tela. Molti utenti vorranno ridimensionare la tela al ridimensionamento della finestra, ma mantenendo invariate le proporzioni. Non è la domanda esatta, ma "si adatta", inserendo la domanda in un contesto leggermente più generale.

La finestra avrà alcune proporzioni (larghezza / altezza), così come l'oggetto tela. Il modo in cui vuoi che questi due aspetti siano correlati l'uno con l'altro è una cosa di cui dovresti essere chiaro, non esiste una risposta "adatta per tutti" a questa domanda - Esaminerò alcuni casi comuni di ciò che potresti volere.

La cosa più importante di cui devi essere chiaro: l'oggetto canvas html ha un attributo di larghezza e un attributo di altezza; e poi, il CSS dello stesso oggetto ha anche un attributo di larghezza e altezza. Queste due larghezze e altezze sono diverse, entrambe sono utili per cose diverse.

La modifica degli attributi di larghezza e altezza è un metodo con cui puoi sempre cambiare la dimensione della tua tela, ma dovrai ridipingere tutto, il che richiederà tempo e non è sempre necessario, perché puoi apportare un po 'di cambiamento di dimensione tramite gli attributi css, nel qual caso non si ridisegna la tela.

Vedo 4 casi di ciò che potresti voler accadere sul ridimensionamento della finestra (tutti a partire da una tela a schermo intero)

1: vuoi che la larghezza rimanga al 100% e vuoi che le proporzioni rimangano com'erano. In tal caso, non è necessario ridisegnare la tela; non hai nemmeno bisogno di un gestore di ridimensionamento della finestra. Tutto ciò che serve è

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

dove ctx è il contesto della tua tela. violino: resizeByWidth

2: si desidera che la larghezza e l'altezza rimangano entrambe al 100% e si desidera che la modifica risultante nelle proporzioni abbia l'effetto di un'immagine allungata. Ora, non è ancora necessario ridisegnare la tela, ma è necessario un gestore di ridimensionamento della finestra. Nel gestore, lo fai

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

violino: messWithAspectratio

3: vuoi che la larghezza e l'altezza rimangano entrambe al 100%, ma la risposta al cambiamento nelle proporzioni è qualcosa di diverso dallo stiramento dell'immagine. Quindi è necessario ridisegnare e farlo nel modo indicato nella risposta accettata.

violino: redraw

4: vuoi che la larghezza e l'altezza siano al 100% al caricamento della pagina, ma rimani costante da allora in poi (nessuna reazione al ridimensionamento della finestra.

violino: fisso

Tutti i violini hanno un codice identico, ad eccezione della riga 63 in cui è impostata la modalità. Puoi anche copiare il codice del violino per eseguirlo sul tuo computer locale, nel qual caso puoi selezionare la modalità tramite un argomento querystring, come? Mode = redraw


1
a proposito: $(ctx.canvas).css("width", "100%");è equivalente a $(canvas).css("width", "100%"); (la tela del contesto è solo la tela)
Brad Kent,

@BradKent quando chiami una funzione helper che fa le "cose ​​su tela" che vuoi fare, puoi o, come argomento (i) 1) passare l'oggetto tela, 2) passare il contesto tela, 3) entrambi. Non mi piace 3), ed ctx.canvasè molto più breve di canvas.getContext('2d')- ecco perché lo faccio 2). Quindi, non esiste una variabile chiamata canvas, ma c'è ctx.canvas. Ecco da dove proviene ctx.canvas.
mathhead include

9

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

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

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

</body>
</html>

con CSS

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

Funziona, ma lascia la mia tela senza una larghezza e un'altezza definite. La larghezza e l'altezza della tela devono essere definite sull'elemento che credo.
aherrick,

@aherrick: No, non è necessario impostare una larghezza / altezza esplicita sull'elemento canvas per farlo funzionare. Questo codice dovrebbe funzionare correttamente.
Jon Adams,

18
In realtà sì, gli elementi della tela hanno bisogno di un set esplicito di larghezza / altezza. Senza di essa sono predefiniti per alcune dimensioni predefinite del browser (in Chrome, penso che sia di 300x150px). Tutto il disegno sulla tela viene interpretato a questa dimensione e quindi ridimensionato al 100% della dimensione della finestra. Prova a disegnare qualsiasi cosa nella tua tela per vedere cosa intendo: sarà distorto.
Mark Kahn,

se stai cercando di rendere la tela larghezza e altezza del 100%, allora non importa nemmeno. lo ridimensioni comunque
jaredwilli

1
Le dimensioni intrinseche dell'elemento canvas equivalgono alla dimensione dello spazio delle coordinate, con i numeri interpretati in pixel CSS. Tuttavia, l'elemento può essere dimensionato arbitrariamente da un foglio di stile. Durante il rendering, l'immagine viene ridimensionata per adattarsi alle dimensioni del layout.
jaredwilli,

8

Stavo cercando di trovare la risposta anche a questa domanda, ma la risposta accettata si stava spezzando per me. Apparentemente usando window.innerWidth non è portatile. Funziona in alcuni browser, ma ho notato che a Firefox non piaceva.

Gregg Tavares ha pubblicato una grande risorsa qui che affronta direttamente questo problema: http://webglfundamentals.org/webgl/lessons/webgl-anti-patterns.html (Vedi 3 e 4 di anti-pattern #).

L'uso di canvas.clientWidth invece di window.innerWidth sembra funzionare bene.

Ecco il ciclo di rendering suggerito da Gregg:

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

(Espandendosi sulla risposta di 動靜 能量)

Disegna la tela per riempire il corpo. Quando si esegue il rendering sulla tela, tenere conto delle sue dimensioni.

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

Per i cellulari, è meglio usarlo

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

perché verrà visualizzato in modo errato dopo aver modificato l'orientamento. La "finestra" verrà aumentata quando si cambia l'orientamento in verticale. Vedere l' esempio completo

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.