Artikel ini membahas tentang cara menggunakan kanvas untuk menggambar efek hujan yang indah. Mari kita lihat efek akhirnya terlebih dahulu.
rendering
menjelaskanLihatlah gambar untuk menganalisis efek apa yang perlu kita capai.
1. Efek jatuhnya tetesan hujan, gerakkan mouse untuk mengontrol arah jatuh
2. Tetesan air hujan jatuh dan berhamburan menjadi butiran air kecil. Arah pergerakan butiran air kecil tersebut sama dengan arah pergerakan mouse.
3. Tetesan air hujan jatuh dalam jarak tertentu dari koordinat tikus dan tersebar menjadi tetesan air kecil. Demikian pula arah pergerakan tetesan air kecil tersebut sama dengan arah pergerakan tikus.
Oke, secara kasar mari kita bagi keseluruhan efek menjadi tiga efek, dan capai ketiga efek ini, dan selesai.
Mari kita lakukan selangkah demi selangkah.
1. Efek jatuhnya tetesan hujan, gerakkan mouse untuk mengontrol arah jatuhIde untuk mencapai efek keseluruhan adalah,
Waktu awalGunakan array untuk menyimpan objek tetesan hujan.
Objek rintik hujan memiliki berbagai atribut yang digunakan untuk merepresentasikan koordinat x rintik hujan, koordinat y, panjang, kecepatan jatuh, warna, dan tanda untuk menentukan apakah akan dihapus.
Saat memperbarui animasiTambahkan sejumlah objek rintik hujan ke dalam larik, lalu lintasi larik, ubah koordinat x dan koordinat y setiap objek rintik hujan, dan gunakan kanvas untuk menggambar dua titik berdasarkan koordinat objek rintik hujan, yang bersama-sama membentuk a rintik hujan.
Jadi kunci untuk mencapai efeknya adalah koordinatnya
Saat menginisialisasi tetesan hujanKoordinat x rintik hujan: bilangan acak
Koordinat rintik hujan y : -100, hal ini untuk memungkinkan tetesan air hujan masuk dari luar daerah yang terlihat
Saat memperbarui animasi Titik hujan x koordinat:原x坐标的值+ speed * speedx
kecepatan adalah nilai tetap, yang menunjukkan kecepatan jatuhnya tetesan air hujan,
speedx adalah variabel yang berhubungan dengan arah pergerakan mouse, speedx = speedx + (maxspeedx - speedx) / 50
Dan maxspeedx merupakan nilai yang didapat berdasarkan arah pergerakan mouse.
maxspeedx = (e.clientX - canvasEl.clientWidth / 2) / (canvasEl.clientWidth / 2)
,
e.clientX: Nilai jarak mouse ke kiri area yang terlihat
canvasEl.clientWidth: lebar seluruh area visual
Dengan kata lain, speedx adalah nilai yang secara bertahap mendekati maxspeedx
Kisaran nilai maxspeedx adalah -1 hingga 1. Semakin mendekati nilainya -1 maka arahnya semakin ke kiri. Semakin mendekati nilai 1 maka arahnya semakin ke kanan.
Mengapa tidak menggunakan maxspeedx saja?
Hal ini untuk mencegah tetesan air hujan berubah arah begitu cepat, daripada langsung mengubah arah setelah pergantian mouse, sebaiknya ada sedikit penundaan agar terlihat lebih baik.
Kalau pakai maxspeedx efeknya seperti ini
Kalau pakai speedx efeknya seperti ini
Koordinat y tetesan hujan:原y坐标的值+ speed
Kecepatannya sama seperti yang disebutkan pada koordinat x di atas, yaitu nilai tetap yang mewakili kecepatan jatuhnya tetesan air hujan.
Oke, yang terakhir, saya menggunakan kanvas untuk menggambar dua titik sesuai koordinat objek rintik hujan, lalu menghubungkannya, dan rintik hujan pun tergambar.
Koordinat titik pertama relatif sederhana. Dapatkan langsung koordinat x dan koordinat y benda rintik hujan yang merupakan koordinat titik tersebut.
Koordinat titik kedua:
x坐标= 雨滴x坐标的值+ 雨滴长度* speedx
y坐标= 雨滴y坐标的值+ 雨滴长度
Terakhir, hubungkan kedua titik tersebut maka akan terbentuk sebuah garis yaitu rintik hujan.
Saat mengatur koordinat x, digunakan kembali variabel kecepatanx Hal ini untuk membuat arah tetesan hujan dan arah jatuhnya tetesan hujan menjadi sama.
Saat speedx tidak digunakan, keadaannya seperti ini
Saat menggunakan speedx, hal ini terjadi
2. Tetesan air hujan jatuh dan berhamburan menjadi butiran air kecil. Arah pergerakan butiran air kecil tersebut sama dengan arah pergerakan mouse.Idenya di sini sebenarnya agak mirip dengan efek di atas.
Waktu awalGunakan array untuk menyimpan objek tetesan air kecil.
Setetes air sebenarnya berbentuk busur lingkaran.
Objek tetesan air kecil memiliki berbagai atribut yang digunakan untuk mewakili koordinat tetesan air kecil, kecepatan pergerakan sumbu x, kecepatan pergerakan sumbu y, jari-jari lingkaran, dan bendera untuk menentukan apakah akan dihapus.
Saat memperbarui animasiTambahkan sejumlah objek tetesan air kecil ke dalam array, lalu lintasi array, ubah koordinat x dan koordinat y dari setiap objek tetesan air kecil, dan gunakan kanvas untuk menggambar busur berdasarkan atribut koordinat dan atribut radius dari objek tetesan air kecil tersebut. objek tetesan air.
Oleh karena itu, fokus pencapaian efek masih pada koordinat
Saat menginisialisasi tetesan air kecilTetesan air kecil muncul ketika tetesan air hujan menghilang, sehingga koordinat tetesan air kecil tersebut juga didasarkan pada koordinat tetesan air hujan tersebut. Saat Anda menghapus tetesan air hujan, akan muncul beberapa tetesan air kecil, dan arah pergerakan tetesan air kecil tersebut adalah juga arah jatuhnya tetesan air hujan. Mouse Arah pergerakannya sama, jadi variabel speedx yang disebutkan di atas tetap diperlukan.
小水珠x坐标: 删除的雨滴x坐标+ 删除的雨滴长度* speedx
小水珠y坐标:删除的雨滴y坐标+ 删除的雨滴长度
Disini kita perlu menggunakan dua atribut benda tetesan air kecil vx (kecepatan perubahan nilai sumbu x) dan vy (kecepatan perubahan nilai sumbu y).
Koordinat x dari tetesan air kecil
vx = vx + speedx / 2
小水珠的x坐标=原x坐标+ vx
,
speedx: variabel yang berhubungan dengan arah pergerakan mouse yang disebutkan di atas. Fungsinya di sini adalah untuk mengontrol arah pergerakan tetesan air kecil ke arah yang sama dengan arah lainnya.
speedx / 2
, tujuan membaginya dengan 2 adalah agar jarak pergerakan tetesan air kecil pada sumbu x menjadi lebih pendek dan terlihat lebih realistis.
Koordinat y dari tetesan air kecil
vy = vy + gravity
小水珠的y坐标= 原y坐标+ vy;
vy: angka negatif
Gravitasi: Gravitasi, bilangan positif, disetel ke 0,5 dalam kode lengkap
Karena koordinat y semula adalah bilangan positif, maka nilai koordinat y tetesan air kecil mula-mula akan mengecil lalu bertambah. Hal ini untuk mencapai efek tetesan air kecil mula-mula naik lalu turun
Terakhir, gunakan saja kanvas untuk menggambar busur berdasarkan atribut koordinat dan atribut radius tetesan air kecil tersebut.
3. Tetesan air hujan jatuh dalam jarak tertentu dari koordinat tikus dan tersebar menjadi tetesan air kecil. Demikian pula arah pergerakan tetesan air kecil tersebut sama dengan arah pergerakan tikus.
Cara menentukan besar kecilnya lingkaran pada gambar sangatlah mudah, misalkan jari-jari lingkaran adalah 35. Kita dapat memperoleh koordinat mouse dengan mengambil koordinat mouse sebagai pusat lingkaran dan 35 sebagai jari-jarinya , kita dapat menentukan besarnya lingkaran.
Kuncinya adalah bagaimana menilai apakah tetesan air hujan sudah memasuki kisaran tersebut. Hal ini memerlukan penggunaan Teorema Pythagoras. Perhatikan gambar.
Karena rintik hujan adalah garis yang menghubungkan dua titik. Untuk melihat apakah rintik hujan sudah masuk dalam rentang tersebut, Anda perlu melihat koordinat titik di bawah rintik hujan. Berapa jarak garis lurus dari mouse adalah panjang ruas garisnya AB pada gambar.
Teorema Pythagoras: Jumlah kuadrat dua sisi siku-siku suatu segitiga siku-siku sama dengan kuadrat sisi miringnya.
AB = Matematika.sqrt(BC BC + AC AC)
BC = koordinat x rintik hujan - koordinat x mouse
AC = koordinat rintik hujan y - koordinat y mouse
Metode Math.sqrt() digunakan untuk menghitung akar kuadrat suatu bilangan
Setelah kita mengetahui jarak garis lurus dari tetesan air hujan ke mouse, bandingkan dengan jari-jari lingkaran. Jika lebih besar dari jari-jarinya maka tidak termasuk dalam jangkauan, sebaliknya maka.
Jika berada dalam jangkauan, hapus tetesan air hujan dan ambil beberapa tetes air kecil.
Meringkaskan
Untuk mencapai efek tersebut, kendalanya terletak pada arah, arah tetesan air hujan, arah jatuhnya tetesan air hujan, dan arah pergerakan tetesan air kecil.Ini semua terkait dengan arah pergerakan mouse setelah menentukan berbagai arah. gunakan kanvas untuk terus menggambar garis berdasarkan jarak.
Kode lengkap
<!doctype html><html lang=en><head> <meta charset=UTF-8> <style> * { margin: 0; padding: 0 } </style></head><body> <id kanvas =canvas style=position: absolute; tinggi: 100%; lebar:100%;></canvas> <script> window.onload = main; function main() {// Dapatkan elemen kanvas var canvasEl = document.getElementById('canvas'); var ctx = canvasEl.getContext('2d'); // Warna latar belakang kanvas var backgroundColor = '#000'; // Lebar kanvas sama dengan lebar area visual canvasEl.width = canvasEl.clientWidth; // Ketinggian kanvas sama dengan tinggi area yang terlihat canvasEl.height = canvasEl.clientHeight; Setelah tetesan air hujan jatuh, mereka berhamburan menjadi tetesan air kecil. var dropList = []; // Gravitasi // Setelah tetesan air hujan jatuh, mereka berhamburan menjadi tetesan air kecil terlebih dahulu kemudian jatuh, terutama karena gravitasi. Karena variabel var gravitasi = 0,5; // Simpan susunan tetesan hujan // Setiap tetesan hujan adalah garis yang digambar var linelist = []; ] Mewakili nilai sumbu x, mousePos[1] mewakili nilai sumbu y var mousePos = [0, 0]; // Mengikuti mouse, tetesan air hujan di area ukuran mouseDis akan menghilang, membentuk efek hamburan // Dengan mousePos sebagai pusat lingkaran, mouseDis adalah Radius, tetesan air hujan dalam rentang ini akan menyebar dan membentuk banyak tetesan air kecil var mouseDis = 35; // Perbarui animasi satu kali dan gambar tetesan hujan lineNum , semakin lebat hujannya lineNum = 3; // Ikuti arah mouse untuk mengubah arah hujan // Setelah mouse bergerak, arah hujan akan berubah secara perlahan, terutama bergantung pada variabel speedx var speedx = 0; nilai yang dapat diambil oleh speedx // Ketika speedx = maxspeedx, arah hujan akan segera berubah seiring dengan arah gerakan mouse var maxspeedx = 0 // Ketika ukuran halaman berubah, atur ulang ukuran kanvas window.onresize = function () { kanvasEl.lebar = canvasEl.clientWidth; canvasEl.height = canvasEl.clientHeight } //Gerakkan mouse untuk memicu event window.onmousemove = function (e) { //Atur mousePos sama dengan koordinat mouse // e.clientX adalah jarak ke kiri area yang terlihat pada jendela browser Jarak // e.clientY adalah jarak dari atas area yang terlihat pada jendela browser mousePos[0] = e.clientX; e.clientY; // Tetapkan nilai maxspeedx melalui posisi mouse, rentang nilainya -1 hingga 1 // Nilai maxspeedx berhubungan dengan // 1. Arah tetesan hujan // 2. Arah tetesan hujan rintik hujan yang jatuh // 3. Kecepatan arah jatuhnya rintik hujan berubah seiring dengan arah gerakan mouse // 4. Arah pergerakan tetesan air kecil // Semakin mendekati nilai 1 maka arahnya semakin ke kanan // Semakin mendekati nilai -1 maka arahnya semakin ke kiri maxspeedx = (e.clientX - canvasEl.clientWidth / 2) / (canvasEl.clientWidth / 2) / (canvasEl.clientWidth / 2); // Berdasarkan parameter, mengembalikan warna rgb, digunakan untuk mengatur warna tetesan hujan function getRgb(r, g, b) { return rgb( + r + , + g + , + b + } // Menggambar tetesan hujan (sebuah garis) function createLine(e) { // Menghasilkan panjang tetesan hujan secara acak var temp = 0.25 * (50 + Math.random() * 100); // Objek garis, mewakili rintik hujan var line = { // Kecepatan jatuh rintik hujan: 5.5 * (Math.random() * 6 + 3), / / Tentukan apakah akan dihapus, jika nilainya benar, hapus die: false, // Tetesan hujan x koordinat posx: e, // Tetesan hujan koordinat y posy: -50, // Panjang tetesan hujan h: temp, // Warna warna rintik hujan: getRgb(Math.floor(temp * 255/75), Math.floor(temp * 255/75), Math.floor(temp * 255/75)) }; // Ciptakan Kebaikan objek garis (rintik hujan), ditambahkan ke array yang menampung tetesan hujan linelist.push(line } // Menggambar setetes air kecil (tetesan air kecil setelah tetesan air hujan berbentuk busur) function createDrop(x, y) { // Objek tetesan, mewakili busur var drop = { // Tentukan apakah akan dihapus, nilai Jika benar, hapus die: false, // Koordinat x pusat busur posx: x, // Koordinat y dari pusat busur posy: y, // vx mewakili kecepatan perubahan nilai sumbu x vx: (Math.random ( ) - 0,5) * 8, // vy mewakili kecepatan perubahan nilai sumbu y. Rentang nilainya adalah: -3 hingga -9 vy: Math.random() * (-6) - 3, // The radius radius busur: Math.random() * 1.5 + 1 }; return drop; } // Menggambar sejumlah tetesan air kecil function madedrops(x, y) { // Menghasilkan bilangan maxi // maxi secara acak Mewakili jumlah tetesan air kecil yang akan diambil var maxi = Math.floor(Math.random() * 5 + 5); for (var i = 0; i < maxi; i++) { dropList.push(createDrop(x, y) } } // Mulai memanggil fungsi update untuk memperbarui jendela animasi.requestAnimationFrame(update); // Perbarui fungsi animasi update() { // Jika array yang menampung tetesan air kecil memiliki konten if (dropList.length > 0) { // Melintasi array yang menampung tetesan air kecil dropList.forEach(function (e) { //Set e.vx, vx mewakili kecepatan perubahan koordinat x // (speedx)/2 adalah untuk, Buat jarak pergerakan tetesan air kecil pada sumbu x menjadi lebih pendek dan terlihat lebih realistis // Buat juga arah pergerakan tetesan air kecil sama dengan arah tetesan air hujan, arah jatuhnya tetesan air hujan, dan arah pergerakan mouse e.vx = e.vx + (speedx / 2); e.posx = e.posx + e.vx; //Set e.vy, vy mewakili kecepatan perubahan koordinat y // Kisaran e.vy adalah -3 hingga -9, dan saat ini e.posy (koordinat y) harus bernilai positif, maka nilai e.posy mula-mula akan berkurang lalu bertambah // yaitu, tetesan air hujan akan tersebar menjadi tetesan air kecil, dan tetesan air kecil tersebut mula-mula akan naik lalu jatuh.e.vy = e.vy + gravitasi; e.posy = e.posy + e.vy; // Jika koordinat y tetesan air kecil lebih besar dari ketinggian area terlihat, atur atribut die ke true // Jika tetesan air kecil melebihi area terlihat, hapus jika (e.vy; posy > canvasEl.clientHeight) { e .die = true } } } // Hapus anggota array yang atribut dienya benar // Hapus tetesan air kecil di luar area yang terlihat untuk (var i = dropList.length - 1; ; saya >= 0; saya- -) { jika (dropList[i].die) { dropList.splice(i, 1 } } // Mengatur kecepatan perubahan arah hujan, rentang nilai: -1 hingga 1 // Ketika speedx = maxspeedx, arah hujan akan Mengubah kecepatanx); segera setelah mouse bergerak arah = speedx + (maxspeedx - speedx) / 50; // Gambarkan sejumlah tetesan air hujan berdasarkan nilai lineNum for (var i = 0; i < lineNum; i++) { // Panggil fungsi createLine, parameternya adalah koordinat x dari rintik hujan createLine(Math.random() * 2 * canvasEl.width - (0.5 * canvasEl.width) } // Tetapkan garis akhir, yaitu garis tetesan air hujan menyebar membentuk banyak tetesan air kecil Position var endLine = canvasEl.clientHeight - Math.random() * canvasEl.clientHeight / 5; Lintasi array yang menampung tetesan air hujan linelist.forEach(function (e) { // Gunakan teorema Pythagoras untuk menentukan rentang penyebaran tetesan air hujan hingga membentuk tetesan air kecil // e.posx + speedx * eh adalah koordinat x dari rintik hujan/ / e.posy + eh adalah koordinat y dari rintik hujan var dis = Math.sqrt(((e.posx + speedx * eh) - mousePos[0]) * ((e.posx + speedx * eh) - mousePos[0]) + (e.posy + eh - mousePos[1]) * (e.posy + eh - mousePos[1])); // Jika berada di area mouseDis, hapus tetesan hujan tersebut dan menggambarnya Beberapa tetesan air kecil (busur) // Sadarilah efek mouse menyentuh tetesan air hujan dan tetesan air hujan tersebut berhamburan menjadi tetesan air kecil if (dis < mouseDis) { // Hapus tetesan air hujan e.die = true; // Gambar beberapa tetesan air kecil (lingkaran busur) madedrops(e.posx + speedx * eh, e.posy + eh } // Jika tetesan air hujan melebihi garis akhir, hapus tetesan air hujan tersebut dan gambarkan beberapa tetesan air kecil (busur) if ((e.posy + eh) > endLine) { e.die = true; madedrops(e.posx + speedx * eh, e.posy + eh } // Jika koordinat y tetesan hujan lebih besar dari ketinggian area terlihat, atur dadu atribut ke benar // Jika tetesan hujan melebihi area yang terlihat, hapus if (e.posy >= canvasEl.clientHeight) { e.die = true } else { // Tingkatkan nilai koordinat y dari tetesan hujan e.posy = e secara bertahap. posy + e.speed ; // Mengubah koordinat x tetesan hujan // * speedx digunakan untuk mengontrol arah jatuhnya tetesan hujan // Membuat arah jatuhnya tetesan hujan sama dengan arah pergerakan mouse e.posx = e .posx + e.kecepatan * kecepatanx; Hapus anggota array yang atribut die-nya benar // Hapus tetesan air hujan di area mouse, di luar garis akhir, dan di luar area yang terlihat untuk (var i = linelist.length - 1; i >= 0; i--) { if (linelist[i].die) { linelist.splice(i, 1 } } // Render render(); // Panggil update secara rekursif untuk mendapatkan efek animasi window.requestAnimationFrame(update } // Fungsi rendering render() { // Menggambar persegi panjang sebesar area yang terlihat ctx.fillStyle = backgroundColor; ctx.fillRect(0, 0, canvasEl.width, canvasEl.height); lineWidth = 5; linelist.forEach(fungsi (baris) { ctx.strokeStyle = garis.warna; ctx.beginPath(); ctx.moveTo(line.posx, line.posy); // * speedx digunakan untuk mengontrol arah tetesan hujan // Membuat arah tetesan hujan sama dengan arah pergerakan mouse ctx.lineTo(line.posx + line. h * speedx, line.posy + line.h); ctx.stroke(); ctx.strokeStyle = #fff; dropList.forEach(fungsi (e) { ctx.beginPath(); ctx.arc(e.posx, e.posy, e.radius, Math.random() * Math.PI * 2, 1 * Math.PI); ctx.stroke(); }); // Batalkan komentar dan Anda dapat melihat rentang mouse/* ctx.beginPath(); mousePos[1], mouseDis, 0, 2 * Math.PI); ctx.stroke(); */ } } </script></body></html>
Di atas adalah keseluruhan isi artikel ini, saya harap dapat bermanfaat untuk pembelajaran semua orang. Saya juga berharap semua orang mendukung VeVb Wulin Network.