web-dev-qa-db-fra.com

Redimensionner le canevas HTML5 pour s’adapter à la fenêtre

Comment puis-je redimensionner automatiquement l'élément HTML5 <canvas> pour l'adapter à la page?

Par exemple, je peux obtenir un <div> à l'échelle en définissant les propriétés height et width à 100%, mais un <canvas> ne sera pas mis à l'échelle, n'est-ce pas?

357
devyn

Je crois avoir trouvé une solution élégante à ceci:

JavaScript

/* important! for alignment, you should make things
 * relative to the canvas' current width/height.
 */
function draw() {
  var ctx = (a canvas context);
  ctx.canvas.width  = window.innerWidth;
  ctx.canvas.height = window.innerHeight;
  //...drawing code...
}

CSS

html, body {
  width:  100%;
  height: 100%;
  margin: 0;
}

Jusqu'à présent, cela n'a eu aucun impact négatif important sur les performances.

337
devyn

La solution suivante a fonctionné pour moi le meilleur. Étant donné que je suis relativement nouveau en codage, j'aime bien avoir la confirmation visuelle que quelque chose fonctionne comme je le souhaite. Je l'ai trouvé sur le site suivant: http://htmlcheats.com/html/resize-the-html5-canvas-dyamically/

Voici le code:

<!DOCTYPE html>

<head>
    <meta charset="utf-8">
    <title>Resize HTML5 canvas dynamically | www.htmlcheats.com</title>
    <style>
    html, body {
      width: 100%;
      height: 100%;
      margin: 0px;
      border: 0;
      overflow: hidden; /*  Disable scrollbars */
      display: block;  /* No floating content on sides */
    }
    </style>
</head>

<body>
    <canvas id='c' style='position:absolute; left:0px; top:0px;'>
    </canvas>

    <script>
    (function() {
        var
        // Obtain a reference to the canvas element using its id.
        htmlCanvas = document.getElementById('c'),
        // Obtain a graphics context on the canvas element for drawing.
        context = htmlCanvas.getContext('2d');

       // Start listening to resize events and draw canvas.
       initialize();

       function initialize() {
           // Register an event listener to call the resizeCanvas() function 
           // each time the window is resized.
           window.addEventListener('resize', resizeCanvas, false);
           // Draw canvas border for the first time.
           resizeCanvas();
        }

        // Display custom canvas. In this case it's a blue, 5 pixel 
        // border that resizes along with the browser window.
        function redraw() {
           context.strokeStyle = 'blue';
           context.lineWidth = '5';
           context.strokeRect(0, 0, window.innerWidth, window.innerHeight);
        }

        // Runs each time the DOM window resize event fires.
        // Resets the canvas dimensions to match window,
        // then draws the new borders accordingly.
        function resizeCanvas() {
            htmlCanvas.width = window.innerWidth;
            htmlCanvas.height = window.innerHeight;
            redraw();
        }
    })();

    </script>
</body> 
</html>

La bordure bleue indique le bord du canevas en cours de redimensionnement et se trouve toujours le long du bord de la fenêtre, visible sur les 4 côtés, ce qui n'était PAS le cas de certaines des réponses précédentes. J'espère que ça aide.

49
Craig Morrison

Fondamentalement, ce que vous devez faire est de lier l'événement onresize à votre corps. Une fois que vous l'avez saisi, il vous suffit de redimensionner la toile à l'aide de window.innerWidth et window.innerHeight.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Canvas Resize</title>

    <script type="text/javascript">
        function resize_canvas(){
            canvas = document.getElementById("canvas");
            if (canvas.width  < window.innerWidth)
            {
                canvas.width  = window.innerWidth;
            }

            if (canvas.height < window.innerHeight)
            {
                canvas.height = window.innerHeight;
            }
        }
    </script>
</head>

<body onresize="resize_canvas()">
        <canvas id="canvas">Your browser doesn't support canvas</canvas>
</body>
</html>
20
equiman

Pour définir la largeur et la hauteur de l'espace de coordonnées de la zone de dessin en fonction des dimensions du client du navigateur, vous devez redimensionner et redessiner chaque fois que le navigateur est redimensionné. 

Une solution moins compliquée consiste à conserver les dimensions pouvant être dessinées dans les variables Javascript, mais à définir les dimensions de la zone de travail en fonction des dimensions screen.width, screen.height. Utilisez CSS pour s'adapter:

#containingDiv { 
  overflow: hidden;
}
#myCanvas {
  position: absolute; 
  top: 0px;
  left: 0px;
} 

La fenêtre du navigateur ne sera généralement jamais plus grande que l’écran lui-même (sauf dans les cas où la résolution de l’écran est mal rapportée, comme cela pourrait être le cas avec deux moniteurs non appariés), ainsi l’arrière-plan ne sera pas affiché et les proportions en pixels ne varieront pas. Les pixels de la toile seront directement proportionnels à la résolution de l'écran, sauf si vous utilisez CSS pour redimensionner la toile. 

18
jerseyboy

Une approche pure CSS s'ajoutant à la solution de @jerseyboy ci-dessus.
Fonctionne dans Firefox (testé en v29), Chrome (testé en v34) et Internet Explorer (testé en v11).

<!DOCTYPE html>
<html>
    <head>
    <style>
        html,
        body {
            width: 100%;
            height: 100%;
            margin: 0;
        }
        canvas {
            background-color: #ccc;
            display: block;
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            width: 100%;
            height: 100%;
        }
    </style>
</head>
<body>
    <canvas id="canvas" width="500" height="500"></canvas>
    <script>
        var canvas = document.getElementById('canvas');
        if (canvas.getContext) {
            var ctx = canvas.getContext('2d');
            ctx.fillRect(25,25,100,100);
            ctx.clearRect(45,45,60,60);
            ctx.strokeRect(50,50,50,50);
        }
    </script>
</body>
</html>

Lien vers l'exemple: http://temporaer.net/open/so/140502_canvas-fit-to-window.html

Mais prenez garde, comme le dit @jerseyboy dans son commentaire:

Le redimensionnement de la toile avec CSS est gênant. Au moins sur Chrome et Les positions Safari, souris/événement tactile ne correspondront pas 1: 1 à positions de pixel de la toile, et vous devrez transformer la coordonnée systèmes.

10
Volker E.

À moins que vous souhaitiez que la zone de dessin optimise automatiquement les données de votre image (c'est ce que dit la réponse de James Black, mais cela ne sera pas joli), vous devez le redimensionner vous-même et redessiner l'image. Centrer une toile

8
Nickolay
function resize() {

    var canvas = document.getElementById('game');
    var canvasRatio = canvas.height / canvas.width;
    var windowRatio = window.innerHeight / window.innerWidth;
    var width;
    var height;

    if (windowRatio < canvasRatio) {
        height = window.innerHeight;
        width = height / canvasRatio;
    } else {
        width = window.innerWidth;
        height = width * canvasRatio;
    }

    canvas.style.width = width + 'px';
    canvas.style.height = height + 'px';
};

window.addEventListener('resize', resize, false);
8
Petr

Si votre div remplit complètement la page Web, vous pourrez alors remplir cette div et disposer ainsi d'un canevas remplissant la div.

Cela peut vous intéresser, car vous devrez peut-être utiliser un CSS pour utiliser un pourcentage, mais cela dépend du navigateur que vous utilisez et de son degré d’accord avec la spécification: http: // www .whatwg.org/specs/applications-Web/travail-actuel/multipage/the-canvas-element.html # the-canvas-element

Les dimensions intrinsèques de la toile élément égal à la taille de la espace de coordonnées, avec les nombres interprété en pixels CSS. Toutefois, l'élément peut être dimensionné de manière arbitraire par une feuille de style. Pendant le rendu, l'image est redimensionnée pour s'adapter à cette présentation Taille.

Vous devrez peut-être obtenir l'offsetWidth et la hauteur de la div ou la hauteur/largeur de la fenêtre et la définir comme valeur de pixel.

4
James Black

Si vous souhaitez conserver les proportions et le faire en CSS pur (compte tenu des proportions), vous pouvez procéder comme suit. La clé est le padding-bottom sur l'élément ::content qui dimensionne l'élément container. Ceci est dimensionné par rapport à la largeur de son parent, qui est 100% par défaut. Le rapport spécifié ici doit correspondre au rapport des tailles sur l'élément canvas.

// Javascript

var canvas = document.querySelector('canvas'),
    context = canvas.getContext('2d');

context.fillStyle = '#ff0000';
context.fillRect(500, 200, 200, 200);

context.fillStyle = '#000000';
context.font = '30px serif';
context.fillText('This is some text that should not be distorted, just scaled', 10, 40);
/*CSS*/

.container {
  position: relative; 
  background-color: green;
}

.container::after {
  content: ' ';
  display: block;
  padding: 0 0 50%;
}

.wrapper {
  position: absolute;
  top: 0;
  right: 0;
  left: 0;
  bottom: 0;
}

canvas {
  width: 100%;
  height: 100%;
}
<!-- HTML -->

<div class=container>
  <div class=wrapper>
    <canvas width=1200 height=600></canvas>  
  </div>
</div>

3
mrmcgreg

CSS

body { margin: 0; } 
canvas { display: block; } 

JavaScript

window.addEventListener("load", function()
{
    var canvas = document.createElement('canvas'); document.body.appendChild(canvas);
    var context = canvas.getContext('2d');

    function draw()
    {
        context.clearRect(0, 0, canvas.width, canvas.height);
        context.beginPath();
        context.moveTo(0, 0); context.lineTo(canvas.width, canvas.height); 
        context.moveTo(canvas.width, 0); context.lineTo(0, canvas.height); 
        context.stroke();
    }
    function resize()
    {
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;
        draw();
    }
    window.addEventListener("resize", resize);
    resize();
});
2
Martin Wantke
(function() {

    // get viewport size
    getViewportSize = function() {
        return {
            height: window.innerHeight,
            width:  window.innerWidth
        };
    };

    // update canvas size
    updateSizes = function() {
        var viewportSize = getViewportSize();
        $('#myCanvas').width(viewportSize.width).height(viewportSize.height);
        $('#myCanvas').attr('width', viewportSize.width).attr('height', viewportSize.height);
    };

    // run on load
    updateSizes();

    // handle window resizing
    $(window).on('resize', function() {
        updateSizes();
    });

}());
1
lokers

Premièrement, vous ne pouvez pas utiliser les attributs width et height pour changer la taille (du moins à ma façon) car cela la casse. Vous pouvez faire ceci: HTML:

<canvas id = 'myCanvas'></canvas>

JS:

var canvas = document.getElementById('myCanvas');

var W = window.innerWidth;
var H = window.innerHeight;
canvas.width = W;
canvas.height = H;

(S'il vous plaît pardonnez-moi pour les fautes de frappe, j'ai tendance à le faire beaucoup)

0
stonefish

Avec jQuery, vous pouvez suivre le redimensionnement de la fenêtre et modifier la largeur de votre toile à l’aide de jQuery. 

Quelque chose comme ca

$( window ).resize(function() {
 		$("#myCanvas").width($( window ).width())
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="myCanvas" width="200" height="100" style="border:1px solid #000000;">

0
Rafael Andrade

Je pense que c'est exactement ce que nous devrions faire: http://www.html5rocks.com/fr/tutorials/casestudies/gopherwoord-studios-resizing-html5-games/

function resizeGame() {
    var gameArea = document.getElementById('gameArea');
    var widthToHeight = 4 / 3;
    var newWidth = window.innerWidth;
    var newHeight = window.innerHeight;
    var newWidthToHeight = newWidth / newHeight;

    if (newWidthToHeight > widthToHeight) {
        newWidth = newHeight * widthToHeight;
        gameArea.style.height = newHeight + 'px';
        gameArea.style.width = newWidth + 'px';
    } else {
        newHeight = newWidth / widthToHeight;
        gameArea.style.width = newWidth + 'px';
        gameArea.style.height = newHeight + 'px';
    }

    gameArea.style.marginTop = (-newHeight / 2) + 'px';
    gameArea.style.marginLeft = (-newWidth / 2) + 'px';

    var gameCanvas = document.getElementById('gameCanvas');
    gameCanvas.width = newWidth;
    gameCanvas.height = newHeight;
}

window.addEventListener('resize', resizeGame, false);
window.addEventListener('orientationchange', resizeGame, false);
0
Arvind Bhardwaj