web-dev-qa-db-fra.com

HTML5 Canvas 100% Largeur Hauteur de la fenêtre?

J'essaie de créer un élément de canevas qui occupe 100% de la largeur et de la hauteur de la fenêtre.

Vous pouvez voir dans mon exemple ici ce qui se produit, mais il ajoute des barres de défilement dans Chrome et FireFox. Comment puis-je empêcher les barres de défilement supplémentaires et fournir simplement la largeur et la hauteur de la fenêtre à la taille de la toile?

136
aherrick

Pour que la largeur et la hauteur de la toile soient toujours complètes en plein écran, ce qui signifie que même lorsque le navigateur est redimensionné, vous devez exécuter votre boucle de dessin dans une fonction qui redimensionne la toile à la fenêtre window.innerHeight et window.innerWidth.

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

C'est ainsi que vous faites correctement la toile pleine largeur et hauteur du navigateur. Vous devez simplement mettre tout le code pour dessiner sur la toile dans la fonction drawStuff ().

241
jaredwilli

Vous pouvez essayer viewport units (CSS3):

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

Je vais répondre à la question plus générale de savoir comment faire en sorte qu'une toile s'adapte de manière dynamique en taille lors du redimensionnement de la fenêtre. La réponse acceptée gère de manière appropriée le cas où largeur et hauteur sont supposées être à 100%, ce qui a été demandé, mais qui modifiera également le rapport de format de la toile. De nombreux utilisateurs souhaiteront que la zone de dessin soit redimensionnée lors du redimensionnement de la fenêtre, tout en conservant le rapport de format intact. Ce n'est pas la question exacte, mais elle "s'intègre", il suffit de placer la question dans un contexte légèrement plus général.

La fenêtre aura un certain rapport d'aspect (largeur/hauteur), ainsi que l'objet canvas. La manière dont vous voulez que ces deux formats d'image se lient l'un à l'autre est une chose sur laquelle vous devez être clair: il n'y a pas de réponse "taille unique" à cette question - je vais passer en revue quelques cas courants de ce que vous pourriez imaginer. vouloir.

La chose la plus importante à propos de laquelle vous devez être clair: l’objet canvas HTML a un attribut width et un attribut height; et puis, le css du même objet a aussi un attribut width et height. Ces deux largeurs et hauteurs sont différentes, les deux sont utiles pour des choses différentes.

Changer les attributs de largeur et de hauteur est une méthode avec laquelle vous pouvez toujours changer la taille de votre toile, mais vous devrez ensuite tout repeindre, ce qui prendra du temps et n'est pas toujours nécessaire, car vous pouvez accomplir certaines modifications de taille. via les attributs css, auquel cas vous ne redessinez pas le canevas.

Je vois 4 cas de ce que vous voudrez peut-être arriver lors du redimensionnement de la fenêtre (tous commençant par une toile plein écran)

1: vous voulez que la largeur reste à 100% et que le format d'image reste tel qu'il était. Dans ce cas, vous n'avez pas besoin de redessiner la toile. vous n'avez même pas besoin d'un gestionnaire de redimensionnement de fenêtre. Tout ce dont tu as besoin c'est

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

où ctx est votre contexte de toile. violon: resizeByWidth

2: vous voulez que la largeur et la hauteur restent à 100% et que le changement de format qui en résulte ait l’effet d’une image étirée. Maintenant, vous n'avez toujours pas besoin de redessiner la toile, mais vous avez besoin d'un gestionnaire de redimensionnement de fenêtre. Dans le gestionnaire, vous faites

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

violon: messWithAspectratio

3: vous voulez que la largeur et la hauteur restent toutes les deux à 100%, mais la réponse au changement de format est quelque chose de différent de l’étirement de l’image. Ensuite, vous devez redessiner et procédez comme indiqué dans la réponse acceptée.

violon: redessiner

4: vous voulez que la largeur et la hauteur soient de 100% sur la charge de la page, tout en restant constantes par la suite (aucune réaction au redimensionnement de la fenêtre.

violon: corrigé

Tous les violons ont un code identique, à l'exception de la ligne 63 où le mode est défini. Vous pouvez également copier le code de violon à exécuter sur votre ordinateur local. Dans ce cas, vous pouvez sélectionner le mode via un argument de chaîne de requête, comme? Mode = redraw

14
mathheadinclouds

Je cherchais aussi à trouver la réponse à cette question, mais la réponse acceptée a été décisive. Apparemment, utiliser window.innerWidth n'est pas portable. Cela fonctionne dans certains navigateurs, mais j’ai remarqué que Firefox ne l’aimait pas.

Gregg Tavares a publié ici une excellente ressource qui traite directement de ce problème: http://webglfundamentals.org/webgl/lessons/webgl-anti-patterns.html (Voir les numéros 3 et 4 de l'anti-pattern ).

Utiliser canvas.clientWidth au lieu de window.innerWidth semble bien fonctionner.

Voici la boucle de rendu suggérée par 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();
8
David

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

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

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

</body>
</html>

avec CSS

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

(Développer la réponse de 能量)

Style de la toile pour remplir le corps. Lors du rendu sur le canevas, tenez compte de sa taille.

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