Ubah ukuran kanvas HTML5 agar sesuai jendela

400

Bagaimana saya bisa secara otomatis skala <canvas>elemen HTML5 agar sesuai dengan halaman?

Sebagai contoh, saya bisa mendapatkan <div>skala dengan mengatur heightdan widthproperti ke 100%, tetapi <canvas>skala tidak akan, bukan?

devyn
sumber
7
mengapa kanvas {lebar: 100%; tinggi: 100%} tidak berfungsi?
zloctb
28
@ zloctb - Itu akan memperbesar kanvas secara langsung, yang meregangkan gambar Anda.
Derek 朕 會 功夫
8
Lihat Dasar - Dasar WebGL untuk penjelasan terperinci tentang apa dan apa yang tidak boleh dilakukan untuk masalah terkait.
legends2k
2
Kanvas juga akan skala baik-baik saja, tambahkan saja css {width: 100%}, isinya tidak akan, itu masalah lain sama sekali!
ejectamenta

Jawaban:

372

Saya yakin saya telah menemukan solusi elegan untuk ini:

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

Sejauh ini, tidak ada dampak kinerja negatif yang besar bagi saya.

devyn
sumber
7
Anda mungkin harus menonaktifkan margin denganbody, html { margin: 0px;}
Nicklas A.
45
Apakah ini lebih baik daripada mendengarkan acara pengubahan ukuran?
Eric
25
@Elisabeth: Untuk menghilangkan scrollbar, tambahkan "overflow: hidden" ke gaya elemen html dan tubuh. Lihat thefutureoftheweb.com/blog/100-percent-height-interface
Denis Washington
17
Saya melakukan ini ditambah saya juga mengatur kanvas untuk menampilkan: blok (sepertinya default untuk menampilkan: inline yang menciptakan ruang ekstra!).
Elisabeth
15
Ini mungkin anti-pola; lihat item ketiga di sini untuk alasan dan perbaikan.
legends2k
67

Solusi berikut ini bekerja untuk saya yang terbaik. Karena saya relatif baru dalam pengkodean, saya ingin memiliki konfirmasi visual bahwa ada sesuatu yang bekerja seperti yang saya harapkan. Saya menemukannya di situs berikut: http://htmlcheats.com/html/resize-the-html5-canvas-dyamically/

Berikut kodenya:

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

Perbatasan biru menunjukkan tepi kanvas ukuran, dan selalu di sepanjang tepi jendela, terlihat di keempat sisi, yang BUKAN kasus untuk beberapa jawaban lain di atas. Semoga ini bisa membantu.

Craig Morrison
sumber
Jawaban ini memecahkan masalah saya. The overflow: hiddendan display: blockadalah apa yang hilang bagi saya untuk mendapatkan kerja ini dengan benar.
Deathicon
1
Tautan rusak
Nic Scozzaro
22

Pada dasarnya apa yang harus Anda lakukan adalah mengikat acara onresize ke tubuh Anda, setelah Anda menangkap acara Anda hanya perlu mengubah ukuran kanvas menggunakan window.innerWidth dan 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>
Equiman
sumber
1
Anda bisa menggunakan pendengar acara.
David Corbin
Ini memiliki margin dan menampilkan scrollbar, plus Anda harus mengubah ukuran layar sebelum melakukan apa pun.
ArtOfWarfare
Bagaimana jika kanvas lebih besar dari viewport (ketika membuat viewport lebih sempit atau lebih pendek)? Solusi ini sepertinya tidak menangani itu.
Lars Gyrup Brink Nielsen
@ArtOfWarfare pertanyaan asli tidak menyebutkan apa pun tentang gaya. Tetapi Anda dapat menyesuaikan dgn css dan menghapus margin dan menyembunyikan scroll bar jika Anda suka. Dan Anda cukup menambahkan `<body onload =" resize_canvas () ">` lalu saat memuat halaman lalu ubah ukuran kanvas.
equiman
@LayZee pertanyaan asli saya tentang skala kanvas agar sesuai dengan halaman , bukan viewport. Itu bisa menjadi pertanyaan lain.
equiman
19

Mengatur kanvas mengkoordinasikan lebar dan tinggi ruang berdasarkan dimensi klien browser mengharuskan Anda untuk mengubah ukuran dan menggambar ulang setiap kali browser diubah ukurannya.

Solusi yang tidak terlalu berbelit-belit adalah mempertahankan dimensi yang dapat digambar dalam variabel Javascript, tetapi mengatur dimensi kanvas berdasarkan pada screen.width, screen.dimensi ketinggian. Gunakan CSS agar sesuai:

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

Jendela browser umumnya tidak akan pernah lebih besar dari layar itu sendiri (kecuali jika resolusi layar salah dilaporkan, karena bisa dengan monitor ganda yang tidak cocok), sehingga latar belakang tidak akan ditampilkan dan proporsi piksel tidak akan bervariasi. Pixel kanvas akan berbanding lurus dengan resolusi layar kecuali Anda menggunakan CSS untuk mengukur skala kanvas.

jerseyboy
sumber
7
Menyimpan ulang kanvas dengan CSS merepotkan. Setidaknya di Chrome dan Safari, posisi acara mouse / sentuh tidak akan sesuai 1: 1 dengan posisi piksel kanvas, dan Anda harus mengubah sistem koordinat.
jerseyboy
14

Sebuah CSS murni pendekatan menambah larutan @jerseyboy di atas.
Bekerja di Firefox (diuji pada v29), Chrome (diuji pada v34) dan Internet Explorer (diuji pada 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>

Tautan ke contoh: http://temporaer.net/open/so/140502_canvas-fit-to-window.html

Tapi berhati-hatilah, seperti yang dinyatakan @jerseyboy dalam komentarnya:

Menyimpan ulang kanvas dengan CSS merepotkan. Setidaknya di Chrome dan Safari, posisi acara mouse / sentuh tidak akan sesuai 1: 1 dengan posisi piksel kanvas, dan Anda harus mengubah sistem koordinat.

Volker E.
sumber
5
Cara CSS merentangkan kanvas, sehingga gambar yang dihasilkan dapat diregangkan. Ini tidak baik dibandingkan dengan mengubah ukuran kanvas. Dengan sedikit penyesuaian, jawaban Craig paling baik.
Nayan
Saya suka solusi ini karena ini membuat kanvas 100% berdasarkan lebar induk.
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);
Petr
sumber
Bagus, ketika rasionya penting
sarkiroka
8

Kecuali jika Anda ingin kanvas untuk meningkatkan data gambar Anda secara otomatis (itulah yang dibicarakan oleh jawaban James Black, tetapi tidak akan terlihat cantik), Anda harus mengubah ukurannya sendiri dan menggambar ulang gambar tersebut. Memusatkan kanvas

Nickolay
sumber
4

Jika div Anda sepenuhnya mengisi halaman web maka Anda dapat mengisi div itu dan memiliki kanvas yang mengisi div itu.

Anda mungkin menemukan ini menarik, karena Anda mungkin perlu menggunakan css untuk menggunakan persentase, tetapi, itu tergantung pada browser yang Anda gunakan, dan seberapa banyak itu sesuai dengan spesifikasi: http://www.whatwg.org/ specs / web-apps / current-work / multipage / the-canvas-element.html # the-canvas-element

Dimensi intrinsik elemen kanvas sama dengan ukuran ruang koordinat, dengan angka yang ditafsirkan dalam piksel CSS. Namun, elemen dapat diukur secara sewenang-wenang oleh style sheet. Selama rendering, gambar diskalakan agar sesuai dengan ukuran tata letak ini.

Anda mungkin perlu mendapatkan offsetWidth dan tinggi div, atau mendapatkan tinggi / lebar jendela dan menetapkannya sebagai nilai piksel.

James Black
sumber
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();
});
Martin Wantke
sumber
3

Jika Anda tertarik untuk mempertahankan rasio aspek dan melakukannya dengan CSS murni (mengingat rasio aspek) Anda dapat melakukan sesuatu seperti di bawah ini. Kuncinya adalah padding-bottompada ::contentelemen yang mengukur containerelemen. Ini berukuran relatif terhadap lebar induknya, yang secara 100%default. Rasio yang ditentukan di sini harus sesuai dengan rasio ukuran pada canvaselemen.

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

mrmcgreg
sumber
2

Menggunakan jQuery Anda dapat melacak ukuran jendela dan mengubah lebar kanvas Anda menggunakan jQuery juga.

Sesuatu seperti itu

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

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

}());
lokers
sumber
0

Saya pikir inilah yang harus kita lakukan dengan tepat: 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);
Arvind Bhardwaj
sumber
-2

Saya menggunakan sketch.js jadi setelah saya menjalankan perintah init untuk kanvas saya mengubah lebar dan tinggi dengan jquery. Ini mendasarkan dimensi pada elemen induk.

$ ('# DrawCanvas'). Sketch (). Attr ('height', $ ('# DrawCanvas'). Parent (). Height ()). Attr ('width', $ ('# DrawCanvas'). Parent ().lebar());

moeiscool
sumber