Ridimensiona la tela HTML5 per adattarla alla finestra


400

Come posso ridimensionare automaticamente l' <canvas>elemento HTML5 per adattarlo alla pagina?

Ad esempio, posso ottenere un <div>ridimensionamento impostando le proprietà heighte widthsu 100%, ma un <canvas>non ridimensionerà, vero?


7
perché tela {larghezza: 100%; altezza: 100%} non funziona?
zloctb,

28
@zloctb - Questo ridimensionerà direttamente la tela, allungando l'immagine.
Derek 朕 會 功夫

8
Consulta i Fondamenti di WebGL per una spiegazione dettagliata di cosa e cosa non fare per i problemi correlati.
legends2k

2
Anche una tela si ridimensionerà bene, basta aggiungere il css {larghezza: 100%}, i suoi contenuti non lo faranno, questa è tutta un'altra faccenda!
ejectamenta,

Risposte:


372

Credo di aver trovato una soluzione elegante a questo:

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;
}

Finora non ha avuto alcun impatto negativo sulle prestazioni per me.


7
Probabilmente devi disabilitare il margine conbody, html { margin: 0px;}
Nicklas A.

45
È preferibile ascoltare l'evento di ridimensionamento?
Eric,

25
@Elisabeth: per eliminare le barre di scorrimento, aggiungi "overflow: hidden" allo stile degli elementi html e body. Vedi thefutureoftheweb.com/blog/100-percent-height-interface
Denis Washington

17
Ho fatto questo in più ho anche impostato canvas per visualizzare: block (sembrava essere predefinito visualizzare: inline che stava creando spazio extra!).
Elisabeth,

15
Questo può essere un anti-pattern; vedere il terzo elemento qui per il motivo e il rimedio.
legends2k

67

La seguente soluzione ha funzionato per me al meglio. Dato che sono relativamente nuovo nella programmazione, mi piace avere la conferma visiva che qualcosa sta funzionando come mi aspetto. L'ho trovato sul seguente sito: http://htmlcheats.com/html/resize-the-html5-canvas-dyamically/

Ecco il codice:

<!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>

Il bordo blu mostra il bordo della tela di ridimensionamento ed è sempre lungo il bordo della finestra, visibile su tutti e 4 i lati, il che NON era il caso di alcune delle altre risposte sopra. Spero che sia d'aiuto.


Questa risposta ha risolto il mio problema. L' overflow: hiddene display: blockè quello che mi mancava per farlo funzionare correttamente.
Deathicon

1
Il collegamento è interrotto
Nic Scozzaro,

22

Fondamentalmente quello che devi fare è legare l'evento onresize al tuo corpo, una volta catturato l'evento devi solo ridimensionare la tela usando window.innerWidth e 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>

1
Potresti semplicemente usare un listener di eventi.
David Corbin,

Questo ha margini e mostra le barre di scorrimento, inoltre devi ridimensionare lo schermo prima di fare qualsiasi cosa.
ArtOfWarfare,

Cosa succede se la tela è più grande della finestra (quando si rende la finestra più stretta o più corta)? Questa soluzione non sembra gestirla.
Lars Gyrup Brink Nielsen il

Le domande originali di @ArtOfWarfare non menzionano nulla sugli stili. Ma puoi stilizzarlo con CSS e rimuovere i margini e nascondere le barre di scorrimento, se lo desideri. E puoi semplicemente aggiungere `<body onload =" resize_canvas () ">` quindi quando il caricamento della pagina quindi ridimensiona la tela.
equiman,

La domanda originale di @LayZee dice che ridimensiona la tela per adattarla alla pagina , non a una finestra. Questa può essere un'altra domanda.
equiman,

19

L'impostazione della larghezza e dell'altezza dello spazio delle coordinate del canvas in base alle dimensioni del client del browser richiede il ridimensionamento e il ridisegno ogni volta che il browser viene ridimensionato.

Una soluzione meno complicata consiste nel mantenere le dimensioni disegnabili nelle variabili Javascript, ma impostare le dimensioni della tela in base alle dimensioni screen.width, screen.height. Usa CSS per adattarsi:

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

La finestra del browser in genere non sarà mai più grande dello schermo stesso (tranne nei casi in cui la risoluzione dello schermo è dichiarata in modo errato, come potrebbe essere con due monitor non corrispondenti), quindi lo sfondo non verrà visualizzato e le proporzioni dei pixel non varieranno. I pixel dell'area di disegno saranno direttamente proporzionali alla risoluzione dello schermo a meno che non si utilizzi CSS per ridimensionare l'area di disegno.


7
Il ridimensionamento della tela con CSS è problematico. Almeno su Chrome e Safari, le posizioni degli eventi mouse / touch non corrisponderanno a 1: 1 con le posizioni dei pixel dell'area di disegno e dovrai trasformare i sistemi di coordinate.
Jerseyboy,

14

Un approccio CSS puro che si aggiunge alla soluzione di @jerseyboy sopra.
Funziona con Firefox (testato nella v29), Chrome (testato nella v34) e Internet Explorer (testato nella 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>

Link all'esempio: http://temporaer.net/open/so/140502_canvas-fit-to-window.html

Ma fai attenzione, come afferma @jerseyboy nel suo commento:

Il ridimensionamento della tela con CSS è problematico. Almeno su Chrome e Safari, le posizioni degli eventi mouse / touch non corrisponderanno a 1: 1 con le posizioni dei pixel dell'area di disegno e dovrai trasformare i sistemi di coordinate.


5
Il modo CSS allunga la tela, quindi le immagini renderizzate vengono allungate. Questo non è buono rispetto al ridimensionamento della tela. Con poche modifiche, la risposta di Craig funziona meglio.
Nayan,

Mi piace questa soluzione in quanto rende la tela al 100% in base alla larghezza del genitore.
Maihan Nijat,

9
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);

Bello, quando il rapporto è importante
sarkiroka,

8

A meno che tu non voglia che la tela esegua l'upscaling automatico dei dati delle tue immagini (è di questo che parla la risposta di James Black, ma non sembrerà carina), devi ridimensionarla da te e ridisegnare l'immagine. Centrare una tela


4

Se il tuo div ha riempito completamente la pagina web, puoi riempire quel div e quindi avere una tela che riempie il div.

Potresti trovare questo interessante, poiché potresti aver bisogno di usare un css per usare la percentuale, ma dipende dal browser che stai usando e da quanto è in accordo con le specifiche: http://www.whatwg.org/ spec / web-apps / corrente-lavoro / multipagina / the-tele-element.html # the-tele-elemento

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.

Potrebbe essere necessario ottenere offsetWidth e l'altezza del div, oppure ottenere l'altezza / larghezza della finestra e impostarlo come valore in pixel.


3

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();
});

3

Se sei interessato a preservare le proporzioni e farlo con CSS puro (date le proporzioni) puoi fare qualcosa come sotto. La chiave è l' padding-bottomsulla ::contentelemento che ridimensiona l' containerelemento. Questo è dimensionato rispetto alla larghezza del suo genitore, che è 100%di default. Il rapporto qui specificato deve corrispondere al rapporto delle dimensioni canvassull'elemento.

// 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>


2

Utilizzando jQuery è possibile tenere traccia del ridimensionamento della finestra e modificare la larghezza della tela utilizzando anche jQuery.

Qualcosa del genere

$( 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;">


1
(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();
    });

}());

0

Penso che sia esattamente ciò che dovremmo fare: http://www.html5rocks.com/en/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);

-2

Sto usando sketch.js, quindi dopo aver eseguito il comando init per la tela, cambio larghezza e altezza con jquery. Basa le dimensioni sull'elemento padre.

$ ( '# DrawCanvas'). Schizzo (). Attr ( 'height', $ ( '# DrawCanvas'). Genitore (). Altezza ()). Attr ( 'width', $ ( '# DrawCanvas'). Genitore ().larghezza());

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.