Berikut ini visual simulasi partikel yang bergerak acak dan memantul ketika mengenai dinding pembatas saja tanpa ada tumbukan dengan partikel lain. Ini relatif mudah dipahami karena setiap perbagian kode sudah diberi keterangan/komentar. Cocok buat pemula yang ingin mengawali pembuatan simulasi sederhana.

Contoh simulasi animasi seperti berikut kemudian diikuti dengan kode yang dapat disalin dan disimpan dalam format html di notepad++ sehingga dapat dibuka secara offline/luring. Unduh notepad++.
Simulasi Partikel dengan HTML+Canvas
Berikut ini kode yang dapat disalin ke format html, misal dengan menggunakan aplikasi notepad atau notepad++ atau yang lain di komputer kemudian disimpan sebagai file html (Hyper Text Markup Language) dengan nama tertentu. Bila sudah silakan buka file ini dengan menggunakan browser seperti Chrome, Edges, Opera, Safari, atau yang lain.
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Simulasi Partikel dengan Canvas</title>
<style>
/* Gaya dasar untuk halaman */
body {
margin: 0;
padding: 20px;
display: flex;
flex-direction: column;
align-items: center;
font-family: Arial, sans-serif;
background-color: mediumorchid;
}
/* Gaya untuk canvas */
#particleCanvas {
background-color: white;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
margin-top: 20px;
}
h1 {
color: #333;
}
.controls {
margin: 15px 0;
}
button {
padding: 8px 15px;
margin: 0 5px;
cursor: pointer;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 4px;
}
</style>
</head>
<body>
<h1>Simulasi Partikel dengan HTML+Canvas</h1>
<div class="controls">
<button id="addParticle">Tambah Partikel</button>
<button id="reset">Reset</button>
</div>
<canvas id="particleCanvas" width="600" height="400"></canvas>
<script>
// =============================================
// INISIALISASI CANVAS DAN KONTEKS
// =============================================
// Mengambil elemen canvas dari DOM
const canvas = document.getElementById('particleCanvas');
// Mendapatkan konteks rendering 2D untuk canvas
const ctx = canvas.getContext('2d');
// =============================================
// VARIABEL GLOBAL DAN KONFIGURASI
// =============================================
// Array untuk menyimpan semua partikel
let particles = [];
// Konfigurasi warna
const colors = {
background: '#f9f9f9', // Warna latar belakang canvas
particleColors: [ // Array warna untuk partikel
'#FF5252', '#FF4081', '#E040FB',
'#7C4DFF', '#536DFE', '#448AFF',
'#40C4FF', '#18FFFF', '#64FFDA',
'#69F0AE', '#B2FF59', '#EEFF41'
],
border: '#333' // Warna border partikel
};
// Konfigurasi simulasi
const config = {
maxParticles: 50, // Jumlah maksimal partikel
minRadius: 5, // Ukuran minimal partikel
maxRadius: 15, // Ukuran maksimal partikel
minSpeed: 1, // Kecepatan minimal
maxSpeed: 3 // Kecepatan maksimal
};
// =============================================
// KELAS PARTIKEL
// =============================================
// Membuat kelas Particle untuk mengelola properti dan perilaku partikel
class Particle {
constructor(x, y) {
// Posisi awal partikel (jika tidak ditentukan, posisi acak)
this.x = x || Math.random() * canvas.width;
this.y = y || Math.random() * canvas.height;
// Ukuran partikel (acak dalam range min-max)
this.radius = config.minRadius + Math.random() * (config.maxRadius - config.minRadius);
// Kecepatan partikel (acak dalam range min-max)
this.speedX = (config.minSpeed + Math.random() * (config.maxSpeed - config.minSpeed)) * (Math.random() < 0.5 ? -1 : 1);
this.speedY = (config.minSpeed + Math.random() * (config.maxSpeed - config.minSpeed)) * (Math.random() < 0.5 ? -1 : 1);
// Warna partikel (dipilih acak dari array colors.particleColors)
this.color = colors.particleColors[Math.floor(Math.random() * colors.particleColors.length)];
// Sudut rotasi untuk efek visual (opsional)
this.rotation = 0;
this.rotationSpeed = Math.random() * 0.02 - 0.01;
}
// Method untuk mengupdate posisi partikel
update() {
// Update posisi berdasarkan kecepatan
this.x += this.speedX;
this.y += this.speedY;
// Update rotasi
this.rotation += this.rotationSpeed;
// Deteksi tumbukan dengan tepi canvas
// Tumbukan dengan tepi kiri/kanan
if (this.x - this.radius <= 0 || this.x + this.radius >= canvas.width) {
this.speedX *= -1; // Membalik arah horizontal
// Koreksi posisi agar tidak terjebak di tepi
if (this.x - this.radius <= 0) this.x = this.radius;
if (this.x + this.radius >= canvas.width) this.x = canvas.width - this.radius;
}
// Tumbukan dengan tepi atas/bawah
if (this.y - this.radius <= 0 || this.y + this.radius >= canvas.height) {
this.speedY *= -1; // Membalik arah vertikal
// Koreksi posisi
if (this.y - this.radius <= 0) this.y = this.radius;
if (this.y + this.radius >= canvas.height) this.y = canvas.height - this.radius;
}
}
// Method untuk menggambar partikel
draw() {
ctx.save(); // Menyimpan state canvas sebelum melakukan transformasi
ctx.translate(this.x, this.y); // Memindahkan origin ke posisi partikel
ctx.rotate(this.rotation); // Rotasi partikel
// Menggambar lingkaran partikel
ctx.beginPath();
ctx.arc(0, 0, this.radius, 0, Math.PI * 2);
ctx.fillStyle = this.color;
ctx.fill();
// Menambahkan border pada partikel
ctx.lineWidth = 2;
ctx.strokeStyle = colors.border;
ctx.stroke();
ctx.restore(); // Mengembalikan state canvas ke semula
}
}
// =============================================
// FUNGSI UTAMA
// =============================================
// Fungsi untuk inisialisasi simulasi
function init() {
// Membuat partikel awal
createParticles(10);
// Memulai animasi
animate();
}
// Fungsi untuk membuat beberapa partikel sekaligus
function createParticles(count) {
// Cek agar tidak melebihi maxParticles
if (particles.length + count > config.maxParticles) {
count = config.maxParticles - particles.length;
if (count <= 0) return;
}
// Membuat partikel baru sebanyak count
for (let i = 0; i < count; i++) {
particles.push(new Particle());
}
}
// Fungsi untuk mereset simulasi
function resetSimulation() {
particles = []; // Mengosongkan array partikel
createParticles(5); // Membuat partikel baru
}
// Fungsi animasi utama (loop rendering)
function animate() {
// Membersihkan canvas setiap frame
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Menggambar background
ctx.fillStyle = colors.background;
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Update dan gambar semua partikel
particles.forEach(particle => {
particle.update();
particle.draw();
});
// Memanggil fungsi animate lagi pada frame berikutnya
requestAnimationFrame(animate);
}
// =============================================
// EVENT LISTENERS
// =============================================
// Menambahkan partikel baru saat tombol diklik
document.getElementById('addParticle').addEventListener('click', () => {
createParticles(3);
});
// Mereset simulasi saat tombol reset diklik
document.getElementById('reset').addEventListener('click', resetSimulation);
// Menambahkan partikel baru saat canvas diklik
canvas.addEventListener('click', (e) => {
// Mendapatkan posisi klik relatif terhadap canvas
const rect = canvas.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
// Membuat partikel baru di posisi klik
if (particles.length < config.maxParticles) {
particles.push(new Particle(x, y));
}
});
// =============================================
// MEMULAI SIMULASI
// =============================================
// Memulai simulasi saat halaman siap
window.addEventListener('load', init);
</script>
</body>
</html>
Selamat mencoba, semoga berhasil.
Tidak ada komentar:
Posting Komentar