Kanvas direntangkan saat menggunakan CSS tetapi normal dengan properti "lebar" / "tinggi"

194

Saya memiliki 2 kanvas, yang satu menggunakan atribut HTML widthdan heightuntuk mengukurnya, yang lain menggunakan CSS:

<canvas id="compteur1" width="300" height="300" onmousedown="compteurClick(this.id);"></canvas>
<canvas id="compteur2" style="width: 300px; height: 300px;" onmousedown="compteurClick(this.id);"></canvas>

Compteur1 menampilkan seperti seharusnya, tetapi tidak compteur2. Konten diambil menggunakan JavaScript pada kanvas 300x300.

Mengapa ada perbedaan tampilan?

teks alternatif

Sirber
sumber

Jawaban:

215

Tampaknya atribut widthdan heightmenentukan lebar atau tinggi sistem koordinat kanvas, sedangkan properti CSS hanya menentukan ukuran kotak di mana ia akan ditampilkan.

Ini dijelaskan di http://www.whatwg.org/html#attr-canvas-width (perlu JS) atau http://www.whatwg.org/c#attr-canvas-width (mungkin akan memakan komputer Anda) :

The canvaselemen memiliki dua atribut untuk mengontrol ukuran bitmap elemen: widthdan height. Atribut-atribut ini, ketika ditentukan, harus memiliki nilai yang bilangan bulat non-negatif yang valid . The aturan untuk parsing bilangan bulat non-negatif harus digunakan untuk mendapatkan nilai-nilai numerik mereka. Jika atribut hilang, atau jika parsing nilainya mengembalikan kesalahan, maka nilai default harus digunakan sebagai gantinya. The widthatribut default untuk 300, dan heightdefault atribut untuk 150.

SamB
sumber
11
memang .. Saya selalu berpikir atribut langsung seperti "lebar" dan "tinggi" sudah usang dalam versi html terbaru ..
Sirber
4
Oh, rupanya itu dijelaskan dengan cukup baik di whatwg.org/specs/web-apps/current-work/multipage/… (bagian #attr-canvas-width). Masalahnya adalah saya mengklik yang salah widthsebelumnya dan pergi ke #dom-canvas-widthbagian sebagai gantinya. Filed w3.org/Bugs/Public/show_bug.cgi?id=9469 tentang hal itu.
SamB
3
Memiliki API yang terlihat seperti tetapi pada dasarnya berbeda dengan yang lain (lebar css, tinggi). Wow.
Ben Aston
1
Penting untuk membedakan ini saat Anda ingin sistem koordinat internal berbeda. (Yaitu untuk menampilkan retina atau permainan gaya 8bit)
Samy Bencherif
1
Ini sangat membingungkan. Kami di mana mencoba mengatur lebar dan tinggi di css. Butuh waktu 2 hari untuk mengatasi stres karena ingin mengetahui 2 interpretasi berbeda tentang lebar dan tinggi. Cuma wow...
NME New Media Entertainment
39

Untuk mengatur widthdan yang heightAnda butuhkan, Anda dapat menggunakan

canvasObject.setAttribute('width', '475');
fermar
sumber
6
+1 el.setAttribute('width', parseInt($el.css('width')))berhasil, terima kasih
Shanimal
9
Bagaimana jika saya ingin kanvas saya memiliki ukuran relatif? Artinya, bagaimana meniru width: 100%;properti css?
Maxbester
1
Jawaban yang bagus, tapi jangan lupa untuk menambahkan canvasObject.setAttribute ('height', '123') juga!
Tom Wells
Saya rasa Anda tidak perlu menggunakan .setAttribute () Saya selalu menggunakan properti .width dan .height
Zorgatone
4
Plain JavaScript (tanpa jQuery) versi menggunakan getComputedStyle : canvas.setAttribute('width', window.getComputedStyle(canvas, null).getPropertyValue("width"));. Ulangi untuk ketinggian.
Ben J
25

Untuk <canvas>elemen, aturan CSS untuk widthdan heightmengatur ukuran aktual elemen kanvas yang akan ditarik ke halaman. Di sisi lain, atribut HTML widthdan heightatur ukuran sistem koordinat atau 'kisi' yang akan digunakan kanvas API.

Sebagai contoh, pertimbangkan ini ( jsfiddle ):

var ctx = document.getElementById('canvas1').getContext('2d');
ctx.fillStyle = "red";
ctx.fillRect(10, 10, 30, 30);

var ctx2 = document.getElementById('canvas2').getContext('2d');
ctx2.fillStyle = "red";
ctx2.fillRect(10, 10, 30, 30);
canvas {
  border: 1px solid black;
}
<canvas id="canvas1" style="width: 50px; height: 100px;" height="50" width="100"></canvas>
<canvas id="canvas2" style="width: 100px; height: 100px;" height="50" width="100"></canvas>

Keduanya memiliki hal yang sama tergambar pada mereka relatif terhadap koordinat internal elemen kanvas. Tetapi di kanvas kedua, persegi panjang merah akan dua kali lebih lebar karena kanvas secara keseluruhan direntangkan melintasi area yang lebih besar oleh aturan CSS.

Catatan: Jika aturan CSS untuk widthdan / atau heighttidak ditentukan maka browser akan menggunakan atribut HTML untuk mengukur elemen sehingga 1 unit dari nilai-nilai ini sama dengan 1px pada halaman. Jika atribut ini tidak ditentukan maka mereka akan default ke widthdari 300dan heightdari 150.

Ben Jackson
sumber
16

Kanvas akan ditarik jika Anda mengatur lebar dan tinggi di CSS Anda. Jika Anda ingin memanipulasi dimensi kanvas secara dinamis, Anda harus menggunakan JavaScript seperti:

canvas = document.getElementById('canv');
canvas.setAttribute('width', '438');
canvas.setAttribute('height', '462');
Hujan biru
sumber
1
Bagus! Terima kasih atas jawaban ini. Saya harus meletakkan canvas.setAttributesebelumnya canvas.getContext('2d')untuk menghindari peregangan gambar.
hhh
6

Browser menggunakan lebar dan tinggi css, tetapi elemen kanvas bersisik berdasarkan lebar dan tinggi kanvas. Dalam javascript, baca lebar dan tinggi css dan atur lebar kanvas untuk itu.

var myCanvas = $('#TheMainCanvas');
myCanvas[0].width = myCanvas.width();
myCanvas[0].height = myCanvas.height();
Russell Harkins
sumber
2

Koreksi shannimal

var el = $('#mycanvas');
el.attr('width', parseInt(el.css('width')))
el.attr('height', parseInt(el.css('height')))
XaviGuardia
sumber
0

CSS menetapkan lebar dan tinggi elemen kanvas sehingga memengaruhi ruang koordinat sehingga semua yang digambar miring

Inilah cara saya tentang cara mengatur lebar dan tinggi dengan Vanilla JavaScript

canvas.width = numberForWidth

canvas.height = numberForHeight
Anthony Gedeon
sumber
-1

Jika Anda menginginkan perilaku dinamis berdasarkan, misalnya kueri media CSS, jangan gunakan atribut lebar dan tinggi kanvas. Gunakan aturan CSS dan kemudian, sebelum mendapatkan konteks render kanvas, tetapkan untuk atribut width dan height lebar dan tinggi gaya CSS:

var elem = document.getElementById("mycanvas");

elem.width = elem.style.width;
elem.height = elem.style.height;

var ctx1 = elem.getContext("2d");
...
Manolo
sumber
Jelas bahwa kanvas akan mendapatkan ukuran koordinat default (300 x 150) jika ukuran hanya ditentukan dalam CSS. Namun, saran ini tidak berfungsi untuk saya, tetapi solusi di bawah tidak.
Per Lindberg
@ PerLindberg - Solusi ini berfungsi jika Anda telah menentukan lebar dan tinggi CSS dalam piksel untuk elemen kanvas.
Manolo