Tugasan:
Penyebaran gelombang, pembelauan, gangguan
Makmal gelombang interaktif
Selamat datang ke makmal gelombang interaktif! Di sini anda boleh meneroka tiga fenomena gelombang utama: perambatan, pembelauan dan gangguan.
Pilih eksperimen:
📡 Perambatan
🌊 Pembelauan
⚡ Gangguan
📊 Profil Gelombang
Perambatan Gelombang
Gelombang merambat ke semua arah dari sumber dengan kelajuan tetap.
🌐 Perambatan Gelombang
Gelombang memindahkan tenaga tanpa memindahkan jirim. Ia merambat dari sumber dalam bulatan sepusat.
Kelajuan perambatan bergantung pada medium
Amplitud menentukan keamatan gelombang
Frekuensi kekal malar semasa perambatan
🌊 Pembelauan Gelombang
Pembelauan ialah keupayaan gelombang untuk membengkok di sekeliling halangan dan melalui celah sempit.
Lebih ketara apabila saiz halangan setanding dengan panjang gelombang
Selepas celah, gelombang tersebar seperti kipas
Menjelaskan perambatan bunyi di sebalik sudut
⚡ Gangguan Gelombang
Gangguan ialah pertindihan gelombang daripada dua sumber koheren (celah berganda Young).
Jalur terang - gangguan membina
Jalur gelap - gangguan memusnah
Jarak antara jalur bergantung pada panjang gelombang
📊 Profil Gelombang
Pandangan sisi menunjukkan bentuk gelombang - gelombang sinus yang bergerak melalui ruang.
Amplitud - sesaran maksimum dari keseimbangan
Panjang gelombang bergantung pada frekuensi dan kelajuan
Semakin tinggi frekuensi, semakin pendek panjang gelombang
🎯 Aplikasi Praktikal
🎵 Akustik
Reka bentuk dewan konsert mengambil kira gangguan gelombang bunyi
📡 Komunikasi Radio
Pembelauan membolehkan gelombang radio membengkok di sekeliling gunung dan bangunan
🔬 Optik
Gangguan cahaya digunakan dalam laser dan holografi
🌊 Oseanografi
Kajian gelombang laut membantu meramalkan cuaca
0.5) {
ctx.globalAlpha = intensity * (amplitude / 40);
ctx.beginPath();
ctx.moveTo(x, 0);
ctx.lineTo(x, canvas.height);
ctx.stroke();
}
}
ctx.globalAlpha = 1;
// Дифрагированные волны справа от щели
const slitSource = { x: barrierX, y: slitY };
for (let angle = -Math.PI/2; angle <= Math.PI/2; angle += Math.PI/20) {
const maxDist = canvas.width - barrierX;
for (let dist = 0; dist < maxDist; dist += 3) {
const x = slitSource.x + dist * Math.cos(angle);
const y = slitSource.y + dist * Math.sin(angle);
if (x >= barrierX && x < canvas.width && y >= 0 && y < canvas.height) {
const wavePhase = (dist / waveLength - time * frequency) * 2 * Math.PI;
const waveValue = Math.sin(wavePhase);
const distanceFactor = Math.max(0, 1 - dist / maxDist);
const angleFactor = Math.cos(angle) * Math.cos(angle);
if (waveValue > 0.3) {
const intensity = waveValue * distanceFactor * angleFactor * (amplitude / 40);
if (intensity > 0.1) {
ctx.fillStyle = 'rgba(255, 152, 0, ' + intensity + ')';
ctx.fillRect(x-1, y-1, 2, 2);
}
}
}
}
}
// Подписи (отодвинули от краев)
ctx.fillStyle = '#fff';
ctx.font = '12px Arial';
ctx.textAlign = 'center';
ctx.fillText("Celah", barrierX, Math.max(30, 20));
ctx.fillText("Pembelauan", Math.min(barrierX + 80, canvas.width - 50), Math.max(slitY - 40, 30));
}
// Рисование интерференции от двух щелей с экраном
function drawInterference() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
const barrierX = canvas.width * 0.25;
const screenX = canvas.width * 0.6; // Экран ближе к щелям
const slitDistance = 50;
const centerY = canvas.height / 2;
const slit1Y = centerY - slitDistance/2;
const slit2Y = centerY + slitDistance/2;
const slitWidth = 6;
const waveSpeed = 50;
const waveLength = waveSpeed / frequency;
// Рисуем барьер с двумя щелями
ctx.fillStyle = '#444';
ctx.fillRect(barrierX - 3, 0, 6, slit1Y - slitWidth/2);
ctx.fillRect(barrierX - 3, slit1Y + slitWidth/2, 6, slit2Y - slitWidth/2 - (slit1Y + slitWidth/2));
ctx.fillRect(barrierX - 3, slit2Y + slitWidth/2, 6, canvas.height - (slit2Y + slitWidth/2));
// Падающие волны слева
ctx.strokeStyle = 'rgba(33, 150, 243, 0.6)';
ctx.lineWidth = 1;
for (let x = 0; x < barrierX; x += waveLength/3) {
const wavePhase = (x / waveLength - time * frequency) * 2 * Math.PI;
const intensity = Math.sin(wavePhase);
if (intensity > 0.5) {
ctx.globalAlpha = intensity * 0.5;
ctx.beginPath();
ctx.moveTo(x, 0);
ctx.lineTo(x, canvas.height);
ctx.stroke();
}
}
ctx.globalAlpha = 1;
// Источники в щелях
ctx.fillStyle = '#ff4444';
ctx.beginPath();
ctx.arc(barrierX, slit1Y, 3, 0, 2 * Math.PI);
ctx.fill();
ctx.beginPath();
ctx.arc(barrierX, slit2Y, 3, 0, 2 * Math.PI);
ctx.fill();
// Анимированные волны от источников
ctx.strokeStyle = 'rgba(76, 175, 80, 0.3)';
ctx.lineWidth = 1;
for (let i = 0; i < 5; i++) {
const radius = (time * 30 + i * 25) % 120; // Уменьшили радиус
if (radius > 5) {
const alpha = Math.max(0, 0.3 - radius / 400);
ctx.globalAlpha = alpha;
// От первой щели
ctx.beginPath();
ctx.arc(barrierX, slit1Y, radius, 0, 2 * Math.PI);
ctx.stroke();
// От второй щели
ctx.beginPath();
ctx.arc(barrierX, slit2Y, radius, 0, 2 * Math.PI);
ctx.stroke();
}
}
ctx.globalAlpha = 1;
// Экран справа
ctx.fillStyle = '#222';
ctx.fillRect(screenX - 2, 0, 4, canvas.height);
// Статичная интерференционная картина на экране
const pattern = createInterferencePattern();
pattern.forEach(stripe => {
const { y, color, alpha, width } = stripe;
ctx.fillStyle = 'rgba(' + color[0] + ', ' + color[1] + ', ' + color[2] + ', ' + alpha + ')';
ctx.fillRect(screenX + 2, y, width, 1);
});
// Подписи (размещены подальше от краев)
ctx.fillStyle = '#fff';
ctx.font = '12px Arial';
ctx.textAlign = 'center';
// Подписи щелей
const labelX = Math.max(barrierX - 25, 40);
ctx.fillText("Celah 1", labelX, Math.max(slit1Y - 10, 20));
ctx.fillText("Celah 2", labelX, Math.min(slit2Y + 20, canvas.height - 10));
// Подпись экрана
ctx.fillText("Skrin", screenX, Math.max(canvas.height - 15, canvas.height - 10));
// Подпись интерференции (размещена безопасно)
const interferenceX = Math.min(screenX + 30, canvas.width - 60);
const interferenceY = Math.max(35, 25);
ctx.font = '11px Arial';
ctx.fillText("Gangguan", interferenceX, interferenceY);
}
// Рисование бокового вида волны
function drawSideView() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
const centerY = canvas.height / 2;
const waveLength = 100 / frequency;
const maxAmplitude = Math.min(amplitude, canvas.height / 3);
// Ось X
ctx.strokeStyle = '#666';
ctx.lineWidth = 1;
ctx.beginPath();
ctx.moveTo(0, centerY);
ctx.lineTo(canvas.width, centerY);
ctx.stroke();
// Разметка оси
ctx.fillStyle = '#888';
ctx.font = '10px Arial';
ctx.textAlign = 'center';
for (let x = 0; x < canvas.width; x += waveLength) {
if (x > 20 && x < canvas.width - 20) { // Отступ от краев
ctx.beginPath();
ctx.moveTo(x, centerY - 5);
ctx.lineTo(x, centerY + 5);
ctx.stroke();
ctx.fillText('λ', x, centerY + 15);
}
}
// Волна
ctx.strokeStyle = '#4CAF50';
ctx.lineWidth = 3;
ctx.beginPath();
for (let x = 0; x < canvas.width; x += 2) {
const phase = (x / waveLength + time * frequency * 2) * 2 * Math.PI;
const y = centerY - maxAmplitude * Math.sin(phase);
if (x === 0) {
ctx.moveTo(x, y);
} else {
ctx.lineTo(x, y);
}
}
ctx.stroke();
// Стрелки амплитуды
ctx.strokeStyle = '#ff4444';
ctx.lineWidth = 2;
const arrowX = canvas.width * 0.25;
// Стрелка вверх
ctx.beginPath();
ctx.moveTo(arrowX, centerY);
ctx.lineTo(arrowX, centerY - maxAmplitude);
ctx.stroke();
// Стрелка вниз
ctx.beginPath();
ctx.moveTo(arrowX, centerY);
ctx.lineTo(arrowX, centerY + maxAmplitude);
ctx.stroke();
// Подписи (размещены с отступом от краев)
ctx.fillStyle = '#fff';
ctx.font = '14px Arial';
ctx.textAlign = 'left';
const labelY = Math.max(centerY - maxAmplitude - 10, 25);
ctx.fillText("Amplitud", Math.max(arrowX - 20, 20), labelY);
ctx.fillText('A = ' + amplitude, Math.max(arrowX - 20, 20), Math.max(labelY - 15, 15));
ctx.textAlign = 'center';
ctx.fillText("Arah perambatan \u2192", canvas.width/2, Math.max(40, 30));
ctx.fillText("Frekuensi = " + frequency + " Hz", canvas.width/2, Math.min(canvas.height - 10, canvas.height - 20));
}
// Анимация
function animate() {
if (!isAnimating) return;
switch(currentExperiment) {
case 'propagation':
drawPropagation();
break;
case 'diffraction':
drawDiffraction();
break;
case 'interference':
drawInterference();
break;
case 'sideview':
drawSideView();
break;
}
time += 0.02;
animationFrame = requestAnimationFrame(animate);
}
// Управление экспериментами
window.switchExperiment = function(experiment) {
const buttons = document.querySelectorAll('.experiment-btn');
const cards = document.querySelectorAll('.theory-card');
const info = document.getElementById('experimentInfo');
buttons.forEach(btn => btn.classList.remove('active'));
cards.forEach(card => card.style.display = 'none');
currentExperiment = experiment;
time = 0;
const btnIds = {
'propagation': 'wavePropBtn',
'diffraction': 'diffractionBtn',
'interference': 'interferenceBtn',
'sideview': 'sideViewBtn'
};
const activeBtn = document.getElementById(btnIds[experiment]);
const activeCard = document.getElementById(experiment + 'Card');
if (activeBtn) activeBtn.classList.add('active');
if (activeCard) activeCard.style.display = 'block';
if (info) {
const titles = {
'propagation': "Perambatan Gelombang",
'diffraction': "Pembelauan Gelombang",
'interference': "Gangguan Gelombang",
'sideview': "Profil Gelombang"
};
const descriptions = {
'propagation': "Gelombang merambat dari sumber dalam bulatan sepusat.",
'diffraction': "Gelombang melalui celah dan tersebar keluar.",
'interference': "Dua celah menghasilkan corak gangguan statik pada skrin.",
'sideview': "Gelombang sinus bergerak melalui ruang."
};
info.innerHTML = '
' + titles[experiment] + ' ' + descriptions[experiment] + '
';
}
};
// Обновление параметров волн
window.updateWaveParams = function() {
const freqSlider = document.getElementById('frequencySlider');
const ampSlider = document.getElementById('amplitudeSlider');
const freqValue = document.getElementById('frequencyValue');
const ampValue = document.getElementById('amplitudeValue');
if (freqSlider && freqValue) {
frequency = parseFloat(freqSlider.value);
freqValue.textContent = frequency + " Hz";
}
if (ampSlider && ampValue) {
amplitude = parseFloat(ampSlider.value);
ampValue.textContent = amplitude;
}
// Пересчитать интерференционную картину при изменении параметров
interferencePattern = null;
};
// Управление анимацией
window.toggleWaveAnimation = function() {
const btn = document.getElementById('playPauseWaveBtn');
if (!btn) return;
if (isAnimating) {
isAnimating = false;
cancelAnimationFrame(animationFrame);
btn.textContent = "\u25b6\ufe0f Main";
} else {
isAnimating = true;
animate();
btn.textContent = "\u23f8\ufe0f Jeda";
}
};
window.resetWaveAnimation = function() {
time = 0;
if (!isAnimating) {
switch(currentExperiment) {
case 'propagation':
drawPropagation();
break;
case 'diffraction':
drawDiffraction();
break;
case 'interference':
drawInterference();
break;
case 'sideview':
drawSideView();
break;
}
}
};
// Запуск анимации
animate();
})()"
style="display: none;">