HTML5+JS
Kesan dicipta menggunakan JavaScript biasa pada elemen kanvas HTML5. Dalam bahagian ini, kami akan merangkumi asas-asasnya: melukis bentuk, melukis dengan ulangan, dan menambah pergerakan.
Melukis Bentuk
Section titled “Melukis Bentuk”Untuk tutorial ini saya akan menggunakan templat lightscript generik:
<head> <meta description="Template"/> <meta publisher="WhirlwindFX" /></head>
<body style="margin: 0; padding: 0;"> <canvas id="exCanvas" width="320" height="200"></canvas></body>
<script> // Get the canvas element from the DOM var c = document.getElementById("exCanvas"); var ctx = c.getContext("2d");
var width = 320; var height = 200; var hue = 0;
function update() { // Code goes here window.requestAnimationFrame(update); }
window.requestAnimationFrame(update);</script>Garisan
Section titled “Garisan”Sama ada menggunakan satu garisan atau banyak, prosesnya kekal sama.
- ctx.beginPath() memulakan bentuk Anda
- ctx.moveTo(x, y) menetapkan titik pertama
- ctx.lineTo(x, y) menetapkan titik seterusnya dan garisan kembali ke yang pertama. Gunakan berbilang lineTo untuk melukis bentuk yang lebih besar.
- Tetapkan ctx.strokeStyle dan/atau ctx.fillStyle (jika bentuk ditutup)
- Gunakan ctx.stroke() untuk melukis garisan, dan ctx.fill() untuk mengisi mana-mana bentuk tertutup. Adalah penting untuk diperhatikan bahawa sehingga titik ini, semuanya adalah hipotetikal — tiada apa yang dilukis sehingga arahan ini dilaksanakan.
Berikut adalah tiga contoh menggunakan garisan:
function update() { // One Line ctx.beginPath(); ctx.moveTo(30, 30); ctx.lineTo(30, 170); ctx.strokeStyle = "blue"; ctx.stroke();
// L ctx.beginPath(); ctx.moveTo(80, 30); ctx.lineTo(80, 100); ctx.lineTo(120, 100); ctx.strokeStyle = "blue"; ctx.stroke();
// Filled Triangle ctx.beginPath(); ctx.moveTo(130, 30); ctx.lineTo(130, 100); ctx.lineTo(170, 100); ctx.lineTo(130, 30); ctx.fillStyle = "red"; ctx.strokeStyle = "blue"; ctx.fill(); ctx.stroke();
window.requestAnimationFrame(update);}
Adalah penting untuk memperhatikan urutan lukisan di sini: segitiga berisi dilukis terakhir, jadi ia akan menutupi dua bentuk lain jika berada di kedudukan yang sama. Selain itu, strok dalam segitiga dilukis selepas isian. Jika kita membalikkan langkah-langkah ini, bahagian dalam strok akan ditutupi oleh isian merah.
Segi Empat Tepat
Section titled “Segi Empat Tepat”Segi empat tepat adalah mudah dan berguna, terutamanya untuk resolusi purata papan kekunci RGB. Prosesnya serupa dengan melukis garisan — gantikan sahaja arahan moveTo dan lineTo dengan rect(x, y, width, height).
function update() { // Basic Square ctx.beginPath(); ctx.rect(30, 30, 75, 75); ctx.strokeStyle = "blue"; ctx.stroke();
// Filled Rectangle ctx.beginPath(); ctx.rect(125, 30, 125, 100); ctx.fillStyle = "red"; ctx.strokeStyle = "blue"; ctx.fill(); ctx.stroke();
window.requestAnimationFrame(update); }
Lengkungan
Section titled “Lengkungan”Lengkungan dilukis dengan memutar titik luar di sekitar titik pusat, dan boleh digunakan untuk mencipta bulatan penuh. Arahan lengkungan adalah ctx.arc(x, y, radius, sudut mula, sudut tamat), di mana kedua-dua ukuran sudut diberikan dalam radian. Berbeza dengan segi empat tepat, lengkungan dilukis dengan asal bentuk (x, y) di pusat lengkungan.
function update() { // Half-circle ctx.beginPath(); ctx.arc(70, 100, 30, 0, Math.PI); ctx.strokeStyle = "blue"; ctx.stroke();
// 3/4 circle ctx.beginPath(); ctx.arc(140, 100, 30, 0, Math.PI * (3/2)); ctx.strokeStyle = "blue"; ctx.stroke();
// Full circle ctx.beginPath(); ctx.arc(210, 100, 30, 0, Math.PI * 2); ctx.strokeStyle = "blue"; ctx.stroke(); ctx.fillStyle = "red"; ctx.fill();
window.requestAnimationFrame(update); }
Seperti yang Anda lihat, lengkungan dilukis mengikut arah jam secara lalai. Ini boleh dibalikkan dengan sudut tamat yang lebih kecil daripada sudut mula, atau dengan menambah “true” sebagai argumen terakhir kepada kaedah ctx.arc().
Melukis Dengan Ulangan
Section titled “Melukis Dengan Ulangan”Melukis tiga bentuk secara manual boleh mengambil dua puluh baris kod, jadi jika Anda perlu melukis seratus bentuk, kita memerlukan pendekatan yang lebih cekap. Gelung dalam JavaScript adalah cara mudah untuk mengulangi tugas, dan ia boleh diterapkan pada lukisan juga.
Berikut adalah contoh menggunakan for-loop untuk melukis deretan kotak berpetak:
function update() {
for(let i = 0; i < 8; i++){
// 1. Create rectangle path and draw the stroke for each. ctx.beginPath(); ctx.rect(i * 20, 20, 20, 20); ctx.strokeStyle = "black"; ctx.stroke();
// 2. If 'i' is even, the fillStyle is black. Otherwise it's white. if(i % 2 == 0){ ctx.fillStyle = "black"; } else { ctx.fillStyle = "white"; } // 3. Fill the shape after setting the fillStyle. ctx.fill(); }
window.requestAnimationFrame(update); }
Berikut adalah contoh while-loop untuk melukis grid berpetak. Saya akan mengubah kecerahan kotak hitam dan hue kotak putih sedikit dalam setiap ulangan menggunakan literal templat.
function update() {
var i = 0;
while(i < 16){
// 1. X and Y calculations with 'row' and 'column' // This operation rounds the result down to the nearest integer. For i = (0-3) the row will be 0, for i = (4-7) the row will be 1, and so on var iRow = Math.floor(i / 4); // This operation finds the remainder after division, limiting column to the (0-3) range. var iCol = i % 4; // Multiply by the square width to find this square's x-origin var ix = iCol * 20; // Multiply by the square height to find this square's y-origin var iy = iRow * 20;
// 2. Path and stroke ctx.beginPath(); ctx.rect(ix, iy, 20, 20); ctx.strokeStyle = "black"; ctx.stroke();
// 3. If the row is even, every other square is filled black. If odd, switch the black squares. Each iteration adds a small amount of the lightness component to the black, and hue to the white. if(iRow % 2 == 0){ if(i % 2 == 0){ // 'Black' ctx.fillStyle = `hsl(1, 0%, ${5 * i}%)` } else { // 'White' ctx.fillStyle = `hsl(${10 * i}, 100%, 50%)`; } } else { if(i % 2 == 0){ // 'White' ctx.fillStyle = `hsl(${10 * i}, 100%, 50%)`; } else { // 'Black' ctx.fillStyle = `hsl(1, 0%, ${5 * i}%)` } }
ctx.fill(); i++; }
window.requestAnimationFrame(update); }
Menambah Pergerakan
Section titled “Menambah Pergerakan”Animasi dalam kanvas hanya dibatasi oleh imaginasi dan pengetahuan matematik Anda. Jika Anda rasa kurang yakin dengan trigonometri atau geometri, saya mengesyorkan melakukan sedikit kajian untuk meningkatkan kemahiran Anda ke tahap seterusnya. Dalam beberapa contoh berikutnya saya akan mengambil bulatan pegun dan melampirkan setiap pemboleh ubah yang mungkin kepada gerakan berayun yang mudah.
Standard emas untuk berayun (pergerakan ke belakang dan ke hadapan secara teratur) adalah dengan mengambil sin() atau cosinus() pemasa. Sama ada operasi akan mengembalikan nilai antara -1 dan 1 untuk SEBARANG nilai yang dimasukkan, walaupun jika ia hanya mengira ke atas. Satu-satunya perbezaan antara keduanya ialah ia sedikit tidak segerak — apabila cos adalah 0, sin adalah -1 atau 1, dan sebaliknya. Kita boleh menggunakan ini untuk keuntungan kita dalam animasi ini —
function update() {
// Find current time in milliseconds, then divide to slow down the animation speed let time = Date.now() / 100;
// Draw a background so the old shapes don't stick around ctx.fillStyle = "white"; ctx.fillRect(0, 0, 320,200);
ctx.beginPath();
//USE ONE EXAMPLE AT A TIME // 1st example - side to side, y is constant ctx.arc(15 * Math.cos(time) + 160, 100, 30, 0, Math.PI * 2); // 2nd example - up and down, x is constant ctx.arc(160, 15 * Math.sin(time) + 100, 30, 0, Math.PI * 2); // 3rd example - circle, x and y are variable ctx.arc(15 * Math.cos(time) + 160, 15 * Math.sin(time) + 100, 30, 0, Math.PI * 2);
ctx.fillStyle = "black"; ctx.fill();
window.requestAnimationFrame(update); }Kiri ke Kanan
Section titled “Kiri ke Kanan”
Atas ke Bawah
Section titled “Atas ke Bawah”
Bulatan Penuh
Section titled “Bulatan Penuh”
Kita hanya mempunyai beberapa atribut lagi untuk diubah dari masa ke masa — jejari bulatan, isian, dan strok. Saya akan meninggalkan sudut lengkungan buat masa ini untuk memastikan bentuk yang mudah kerana selebihnya akan agak mencolok.
function update() {
let time = Date.now() / 100;
ctx.fillStyle = "white"; ctx.fillRect(0, 0, 320,200);
ctx.beginPath(); ctx.arc(15 * Math.cos(time) + 160, 15 * Math.sin(time) + 100, 30 + 15 * Math.sin(time), 0, Math.PI * 2);
ctx.fillStyle = `hsl(${180 + 180 * Math.cos(time)}, 100%, 50%)`; ctx.fill();
ctx.strokeStyle = `hsl(${180 + 180 * Math.sin(time)}, 100%, 50%)`; ctx.stroke();
window.requestAnimationFrame(update); }
Setiap atribut setiap bentuk yang telah kita cipta setakat ini boleh diubah dari masa ke masa, dan setiap animasi yang saya buat adalah gabungan kemahiran di atas. Untuk maklumat lanjut tentang membuat animasi yang boleh digunakan semula dan cekap, lihat halaman Callbacks kami!