CATATAN : Ini ada hubungannya dengan bagaimana elemen kanvas yang ada dirender saat diperbesar , bukan dengan bagaimana garis atau grafik dirender ke permukaan kanvas . Dengan kata lain, ini memiliki semuanya harus dilakukan dengan interpolasi dari elemen skala , dan tidak ada hubungannya dengan antialiasing grafis yang digambar di atas kanvas. Saya tidak peduli dengan bagaimana browser menggambar garis; Saya peduli tentang bagaimana browser merender elemen kanvas itu sendiri saat diskalakan.
Apakah ada properti kanvas atau setelan browser yang dapat saya ubah secara terprogram untuk menonaktifkan interpolasi saat menskalakan <canvas>
elemen? Solusi lintas-browser sangat ideal tetapi tidak penting; Browser berbasis webkit adalah target utama saya. Performa sangat penting.
Pertanyaan ini paling mirip tetapi tidak cukup menggambarkan masalah. Untuk apa nilainya, saya telah mencoba image-rendering: -webkit-optimize-contrast
tidak berhasil.
Aplikasi ini akan menjadi game bergaya "retro" 8-bit yang ditulis dalam HTML5 + JS untuk memperjelas apa yang saya butuhkan.
Sebagai ilustrasi, berikut adalah sebuah contoh. ( versi langsung )
Misalkan saya memiliki kanvas 21x21 ...
<canvas id='b' width='21' height='21'></canvas>
... yang memiliki css yang membuat elemen 5 kali lebih besar (105x105):
canvas { border: 5px solid #ddd; }
canvas#b { width: 105px; height: 105px; } /* 5 * 21 = 105 */
Saya menggambar 'X' sederhana di kanvas seperti ini:
$('canvas').each(function () {
var ctx = this.getContext("2d");
ctx.moveTo(0,0);
ctx.lineTo(21,21);
ctx.moveTo(0,21);
ctx.lineTo(21,0);
ctx.stroke();
});
Gambar di sebelah kiri adalah gambar yang dibuat oleh Chromium (14.0). Gambar di sebelah kanan adalah yang saya inginkan (digambar dengan tangan untuk tujuan ilustrasi).
sumber
Jawaban:
Terakhir Diperbarui: 2014-09-12
Jawabannya mungkin suatu hari nanti . Untuk saat ini, Anda harus melakukan peretasan untuk mendapatkan apa yang Anda inginkan.
image-rendering
Draf kerja CSS3 menguraikan properti baru,
image-rendering
yang harus melakukan apa yang saya inginkan:Spesifikasi menguraikan tiga nilai yang diterima:
auto
,crisp-edges
, danpixelated
.Standar? Lintas browser?
Karena ini baru draft kerja , tidak ada jaminan akan menjadi standar. Dukungan browser saat ini sangat buruk.
Jaringan Pengembang Mozilla memiliki halaman yang cukup menyeluruh yang didedikasikan untuk keadaan seni saat ini yang sangat saya sarankan untuk dibaca.
Pengembang Webkit awalnya memilih untuk menerapkan ini sebagai tentatif
-webkit-optimize-contrast
, tetapi Chromium / Chrome tampaknya tidak menggunakan versi Webkit yang menerapkan ini.Perbarui: 2014-09-12
Chrome 38 sekarang mendukung
image-rendering: pixelated
!Firefox memiliki laporan bug yang terbuka untuk
image-rendering: pixelated
diterapkan, tetapi-moz-crisp-edges
berfungsi untuk saat ini.Larutan?
Solusi paling lintas platform dan khusus CSS sejauh ini adalah:
Sayangnya ini belum berfungsi pada semua platform HTML5 utama (Chrome, khususnya).
Tentu saja, seseorang dapat secara manual memperbesar gambar menggunakan interpolasi tetangga terdekat ke permukaan kanvas resolusi tinggi dalam javascript, atau bahkan gambar skala sebelumnya di sisi server, tetapi dalam kasus saya ini akan sangat mahal sehingga ini bukan opsi yang layak.
ImpactJS menggunakan teknik penskalaan tekstur untuk mengatasi semua FUD ini. Pengembang Impact, Dominic Szablewski, menulis artikel yang sangat mendalam tentang ini (dia bahkan mengutip pertanyaan ini dalam penelitiannya).
Lihat jawaban Simon untuk solusi berbasis kanvas yang bergantung pada
imageSmoothingEnabled
properti (tidak tersedia di browser lama, tetapi lebih sederhana daripada penskalaan awal dan cukup banyak didukung).Demo Langsung
Jika Anda ingin menguji properti CSS yang dibahas dalam artikel MDN tentang
canvas
elemen, saya telah membuat biola ini yang akan menampilkan sesuatu seperti ini, buram atau tidak, tergantung pada browser Anda:sumber
Jawaban baru 31/7/2012
Ini akhirnya ada di spesifikasi kanvas!
Spesifikasi baru-baru ini menambahkan properti yang dipanggil
imageSmoothingEnabled
, yang defaultnyatrue
dan menentukan apakah gambar yang digambar pada koordinat non-integer atau skala yang digambar akan menggunakan algoritme yang lebih halus. Jika disetel kefalse
tetangga terdekat digunakan, menghasilkan gambar yang kurang halus dan malah membuat piksel tampak lebih besar.Perataan gambar baru saja ditambahkan ke spesifikasi kanvas dan tidak didukung oleh semua browser, tetapi beberapa browser telah menerapkan versi properti ini yang diawali vendor. Pada konteks yang ada
mozImageSmoothingEnabled
di Firefox danwebkitImageSmoothingEnabled
di Chrome dan Safari, dan pengaturan ini ke false akan menghentikan anti-aliasing agar tidak terjadi. Sayangnya, pada saat penulisan, IE9 dan Opera belum mengimplementasikan properti ini, diawali vendor atau sebaliknya.Pratinjau: JSFiddle
Hasil:
sumber
Sunting 31/7/2012 - Fungsi ini sekarang ada di spesifikasi kanvas! Lihat jawaban terpisah di sini:
https://stackoverflow.com/a/11751817/154112
Jawaban lama ada di bawah untuk anak cucu.
Bergantung pada efek yang Anda inginkan, Anda memiliki ini sebagai salah satu opsi:
http://jsfiddle.net/wa95p/
Yang menciptakan ini:
Mungkin bukan yang Anda inginkan. Tetapi jika Anda hanya ingin memiliki zero blur maka itu adalah tiketnya, jadi saya akan menawarkannya untuk berjaga-jaga.
Opsi yang lebih sulit adalah menggunakan manipulasi piksel dan menulis algoritme sendiri untuk pekerjaan itu. Setiap piksel dari gambar pertama menjadi blok piksel 5x5 pada gambar baru. Tidak akan terlalu sulit untuk melakukannya dengan imagedata.
Tetapi Canvas dan CSS saja tidak akan membantu Anda di sini untuk menskalakan satu sama lain dengan efek tepat yang Anda inginkan.
sumber
image-rendering: -webkit-optimize-contrast
harus melakukan trik tetapi sepertinya tidak melakukan apa-apa. Saya mungkin melihat ke dalam menggulung fungsi untuk memperbesar konten kanvas menggunakan interpolasi tetangga terdekat.Di google chrome, pola gambar kanvas tidak diinterpolasi.
Berikut adalah contoh kerja yang diedit dari jawaban namuol http://jsfiddle.net/pGs4f/
sumber
Solusi Saviski yang dijelaskan di sini cukup menjanjikan, karena berhasil pada:
Namun tidak berfungsi berikut ini, tetapi efek yang sama dapat dicapai menggunakan rendering gambar CSS:
Masalahnya adalah ini, karena ctx.XXXImageSmoothingEnabled tidak berfungsi dan rendering gambar tidak berfungsi:
sumber