HTML5 Kanvas Tinggi 100% Lebar Penayangan?

151

Saya mencoba membuat elemen kanvas yang membutuhkan 100% lebar dan tinggi viewport.

Anda dapat melihat dalam contoh saya di sini yang sedang terjadi, namun menambahkan bilah gulir di Chrome dan FireFox. Bagaimana saya bisa mencegah bilah gulir tambahan dan hanya memberikan lebar dan tinggi jendela persis seperti ukuran kanvas?

aherrick
sumber
1
Lihat juga: stackoverflow.com/questions/4037212
hippietrail
Mengingatkan saya pada sketsa komedi Fonejacker yang agak lucu: youtu.be/6oj_oLMD688?t=22s
Francis Booth

Jawaban:

258

Untuk membuat kanvas layar lebar penuh dan tinggi selalu, yang berarti bahkan ketika browser diubah ukurannya, Anda perlu menjalankan loop menggambar Anda dalam suatu fungsi yang mengubah ukuran kanvas ke jendela.

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

Itulah cara Anda membuat kanvas dengan benar lebar dan tinggi browser. Anda hanya perlu meletakkan semua kode untuk menggambar ke kanvas dalam fungsi drawStuff ().

jaredwilli
sumber
2
Mengapa perlu untuk menghapus padding dan mengatur lebar, tinggi hingga 100%?
Kos
3
Saya percaya ini terutama untuk mengganti stylesheet pengguna yang standar perambannya miliki. Jika Anda menggunakan semacam menormalkan atau mereset file css, ini tidak perlu karena sudah diurus.
jaredwilli
2
Jika Anda mengharapkan ukuran yang cukup banyak; misalnya pada perangkat potret / lansekap, Anda ingin debouncemengubah ukurannya jika tidak Anda akan membanjiri browser.
dooburt
24
display: block: Ini tidak hanya menghapus scrollbar, tetapi menghilangkan 2px dari ketinggian badan dokumen, yang biasanya ditambahkan di bawah baris teks di dalam blok. Jadi +1 untuk itu
Neptilo
2
ditambah satu tanpa jQuery
Félix Gagnon-Grenier
26

Anda dapat mencoba unit viewport (CSS3):

canvas { 
  height: 100vh; 
  width: 100vw; 
  display: block;
}
Vitalii Fedorenko
sumber
5
Tambahkan display: block;dan itu berhasil.
superlukas
18
Saya mencoba ini dan menemukan bahwa di Chrome dan Firefox, kanvas hanya menunjukkan gambar membentang ke viewport penuh. Bahkan elemen yang baru digambar juga diregangkan.
Sungai Vivian
8
@Aniel benar - jawaban ini salah . Ini tidak akan mengatur dimensi internal konteks kanvas, melainkan dimensi elemen DOM. Untuk perbedaannya, lihat jawaban saya untuk pertanyaan terkait .
Dan Dascalescu
19
Metode ini tidak berfungsi, itu membentang teks. Sayangnya Anda harus menggunakan JS.
i336_
16

Saya akan menjawab pertanyaan yang lebih umum tentang bagaimana mengubah ukuran kanvas secara dinamis sesuai ukuran jendela. Jawaban yang diterima dengan tepat menangani kasus di mana lebar dan tinggi seharusnya 100%, yang diminta, tetapi juga akan mengubah rasio aspek kanvas. Banyak pengguna menginginkan ukuran kanvas pada ukuran jendela, tetapi dengan tetap menjaga rasio aspek tidak tersentuh. Ini bukan pertanyaan yang tepat, tetapi "cocok", hanya menempatkan pertanyaan ke dalam konteks yang sedikit lebih umum.

Jendela akan memiliki beberapa aspek rasio (lebar / tinggi), dan begitu juga objek kanvas. Bagaimana Anda ingin kedua aspek rasio ini saling berhubungan adalah satu hal yang harus Anda jelaskan, tidak ada jawaban "satu ukuran cocok untuk semua" untuk pertanyaan itu - saya akan membahas beberapa kasus umum tentang apa yang mungkin Anda lakukan ingin.

Paling penting Anda harus jelas tentang: objek kanvas html memiliki atribut lebar dan atribut tinggi; dan kemudian, css dari objek yang sama juga memiliki atribut width dan height. Kedua lebar dan tinggi itu berbeda, keduanya berguna untuk hal yang berbeda.

Mengubah atribut lebar dan tinggi adalah salah satu metode yang dengannya Anda selalu dapat mengubah ukuran kanvas Anda, tetapi kemudian Anda harus mengecat semuanya, yang akan memakan waktu dan tidak selalu diperlukan, karena sejumlah perubahan ukuran yang dapat Anda lakukan melalui atribut css, dalam hal ini Anda tidak menggambar ulang kanvas.

Saya melihat 4 kasus apa yang Anda mungkin ingin terjadi pada ukuran jendela (semua dimulai dengan kanvas layar penuh)

1: Anda ingin lebar tetap 100%, dan Anda ingin rasio aspek tetap seperti semula. Dalam hal ini, Anda tidak perlu menggambar ulang kanvas; Anda bahkan tidak memerlukan penangan ukuran jendela. Yang kamu butuhkan adalah

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

di mana ctx adalah konteks kanvas Anda. biola: resizeByWidth

2: Anda ingin lebar dan tinggi tetap 100%, dan Anda ingin perubahan rasio aspek yang dihasilkan memiliki efek gambar yang ditarik keluar. Sekarang, Anda masih tidak perlu menggambar ulang kanvas, tetapi Anda perlu penangan ukuran jendela. Di pawang, Anda lakukan

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

biola: messWithAspectratio

3: Anda ingin lebar dan tinggi tetap 100%, tetapi jawaban untuk perubahan rasio aspek adalah sesuatu yang berbeda dari peregangan gambar. Maka Anda perlu menggambar ulang, dan melakukannya dengan cara yang dijelaskan dalam jawaban yang diterima.

biola: gambar ulang

4: Anda ingin lebar dan tinggi 100% memuat halaman, tetapi tetap konstan setelahnya (tidak ada reaksi terhadap perubahan ukuran jendela.

biola: diperbaiki

Semua biola memiliki kode yang identik, kecuali untuk baris 63 tempat mode diatur. Anda juga dapat menyalin kode biola untuk dijalankan di mesin lokal Anda, dalam hal ini Anda dapat memilih mode melalui argumen querystring, seperti? Mode = redraw

matematika seperti awan
sumber
1
fyi: $(ctx.canvas).css("width", "100%");setara dengan $(canvas).css("width", "100%"); (kanvas konteksnya hanya kanvas)
Brad Kent
@BradKent ketika Anda memanggil fungsi pembantu yang melakukan "kanvas-hal" yang ingin Anda lakukan, Anda dapat, sebagai argumen (s) 1) melewati objek kanvas, 2) melewati konteks kanvas, 3) keduanya. Saya tidak suka 3), dan ctx.canvasjauh lebih pendek dari canvas.getContext('2d')- itu sebabnya saya lakukan 2). Oleh karena itu, tidak ada variabel yang disebut kanvas, tetapi ada ctx.canvas. Di situlah ctx.canvas berasal.
mathheadinclouds
9

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

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

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

</body>
</html>

dengan CSS

body { 
       margin: 0; 
       padding: 0
     }
#c { 
     position: absolute; 
     width: 100%; 
     height: 100%; 
     overflow: hidden
   }
nonopolaritas
sumber
Ini bekerja, tetapi ia meninggalkan kanvas saya tanpa lebar dan tinggi yang ditentukan. Lebar kanvas dan tinggi kanvas harus ditentukan pada elemen yang saya percayai.
aherrick
@ aherrick: Tidak, Anda tidak harus memiliki lebar / tinggi eksplisit yang ditetapkan pada elemen kanvas agar dapat berfungsi. Kode ini seharusnya berfungsi dengan baik.
Jon Adams
18
Sebenarnya ya, elemen kanvas memang membutuhkan set lebar / tinggi yang eksplisit. Tanpa itu mereka default untuk beberapa browser yang sudah diatur sebelumnya (dalam chrome, saya pikir itu 300x150px) ukuran. Semua gambar ke kanvas ditafsirkan pada ukuran ini dan kemudian diskalakan hingga 100% dari ukuran viewport. Cobalah menggambar apa pun di kanvas Anda untuk melihat apa yang saya maksud - itu akan terdistorsi.
Mark Kahn
jika Anda mencoba membuat kanvas 100% lebar dan tinggi maka itu tidak masalah sama sekali. Anda baru saja mengubah ukurannya
jaredwilli
1
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.
jaredwilli
8

Saya mencari untuk menemukan jawaban untuk pertanyaan ini juga, tetapi jawaban yang diterima itu mematahkan bagi saya. Tampaknya menggunakan window.innerWidth tidak portabel. Itu berfungsi di beberapa browser, tetapi saya perhatikan Firefox tidak menyukainya.

Gregg Tavares memposting sumber yang bagus di sini yang membahas masalah ini secara langsung: http://webglfundamentals.org/webgl/lessons/webgl-anti-patterns.html (Lihat 3 dan 4 pola anti-pola #).

Menggunakan canvas.clientWidth alih-alih window.innerWidth tampaknya berfungsi dengan baik.

Inilah loop render yang disarankan 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();
David
sumber
2

(Memperluas jawaban 動靜 能量)

Gaya kanvas untuk mengisi tubuh. Saat merender ke kanvas memperhitungkan ukurannya.

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

Untuk ponsel, lebih baik menggunakannya

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

karena akan ditampilkan secara tidak benar setelah mengubah orientasi. "viewport" akan meningkat ketika mengubah orientasi ke potret. Lihat contoh lengkap

dzanis
sumber