<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>弹性碰撞演示</title>
<style>
body {
font-family: 'Microsoft YaHei', sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
background-color: #f5f5f5;
}
h1 {
color: #2c3e50;
text-align: center;
}
.container {
display: flex;
flex-direction: column;
gap: 20px;
}
.control-panel {
background-color: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.slider-container {
margin-bottom: 15px;
}
label {
display: inline-block;
width: 120px;
font-weight: bold;
}
input[type="range"] {
width: 300px;
vertical-align: middle;
}
.value-display {
display: inline-block;
width: 60px;
text-align: right;
margin-left: 10px;
}
button {
background-color: #3498db;
color: white;
border: none;
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
margin-right: 10px;
}
button:hover {
background-color: #2980b9;
}
.animation-area {
background-color: white;
height: 200px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
position: relative;
overflow: hidden;
}
.ball {
position: absolute;
border-radius: 50%;
width: 50px;//
height: 50px;
top: 75px;
text-align: center;
line-height: 50px;
color: white;
font-weight: bold;
}
#ball1 {
background-color: #e74c3c;
left: 100px;
}
#ball2 {
background-color: #2ecc71;
left: 400px;
}
.results {
background-color: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 10px;
}
th, td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
th {
background-color: #f2f2f2;
}
.formula {
background-color: #f8f9fa;
padding: 10px;
border-radius: 4px;
margin-top: 15px;
font-family: monospace;
}
</style>
</head>
<body>
<h1>弹性碰撞演示</h1>
<div class="container">
<div class="control-panel">
<h2>参数设置</h2>
<div class="slider-container">
<label for="m1">小球1质量 (kg):</label>
<input type="range" id="m1" min="1" max="10" step="0.1" value="2">
<span id="m1-value" class="value-display">2</span>
</div>
<div class="slider-container">
<label for="m2">小球2质量 (kg):</label>
<input type="range" id="m2" min="1" max="10" step="0.1" value="1">
<span id="m2-value" class="value-display">1</span>
</div>
<div class="slider-container">
<label for="v1">小球1初速度 (m/s):</label>
<input type="range" id="v1" min="-10" max="10" step="0.1" value="3">
<span id="v1-value" class="value-display">3</span>
</div>
<div class="slider-container">
<label for="v2">小球2初速度 (m/s):</label>
<input type="range" id="v2" min="-10" max="10" step="0.1" value="0">
<span id="v2-value" class="value-display">0</span>
</div>
<div style="margin-top: 20px;">
<button id="start-btn">开始碰撞</button>
<button id="reset-btn">重置</button>
</div>
</div>
<div class="animation-area">
<div id="ball1" class="ball">m1</div>
<div id="ball2" class="ball">m2</div>
</div>
<div class="results">
<h2>计算结果</h2>
<table>
<tr>
<th>物理量</th>
<th>碰撞前</th>
<th>碰撞后</th>
</tr>
<tr>
<td>小球1速度 (m/s)</td>
<td id="v1-before">3.0</td>
<td id="v1-after">-</td>
</tr>
<tr>
<td>小球2速度 (m/s)</td>
<td id="v2-before">0.0</td>
<td id="v2-after">-</td>
</tr>
<tr>
<td>系统动量 (kg·m/s)</td>
<td id="p-before">6.0</td>
<td id="p-after">-</td>
</tr>
<tr>
<td>系统动能 (J)</td>
<td id="k-before">9.0</td>
<td id="k-after">-</td>
</tr>
</table>
<div class="formula">
<p>弹性碰撞公式:</p>
<p>v<sub>1</sub>' = (m<sub>1</sub>-m<sub>2</sub>)v<sub>1</sub> + 2m<sub>2</sub>v<sub>2</sub> / (m<sub>1</sub>+m<sub>2</sub>)</p>
<p>v<sub>2</sub>' = (m<sub>2</sub>-m<sub>1</sub>)v<sub>2</sub> + 2m<sub>1</sub>v<sub>1</sub> / (m<sub>1</sub>+m<sub>2</sub>)</p>
</div>
</div>
</div>
<script>
// 获取DOM元素
const m1Slider = document.getElementById('m1');
const m2Slider = document.getElementById('m2');
const v1Slider = document.getElementById('v1');
const v2Slider = document.getElementById('v2');
const m1Value = document.getElementById('m1-value');
const m2Value = document.getElementById('m2-value');
const v1Value = document.getElementById('v1-value');
const v2Value = document.getElementById('v2-value');
const ball1 = document.getElementById('ball1');
const ball2 = document.getElementById('ball2');
const v1Before = document.getElementById('v1-before');
const v2Before = document.getElementById('v2-before');
const v1After = document.getElementById('v1-after');
const v2After = document.getElementById('v2-after');
const pBefore = document.getElementById('p-before');
const pAfter = document.getElementById('p-after');
const kBefore = document.getElementById('k-before');
const kAfter = document.getElementById('k-after');
const startBtn = document.getElementById('start-btn');
const resetBtn = document.getElementById('reset-btn');
// 更新显示值
function updateDisplayValues() {
m1Value.textContent = m1Slider.value;
m2Value.textContent = m2Slider.value;
v1Value.textContent = v1Slider.value;
v2Value.textContent = v2Slider.value;
ball1.textContent = `m1=${m1Slider.value}`;
ball2.textContent = `m2=${m2Slider.value}`;
v1Before.textContent = v1Slider.value;
v2Before.textContent = v2Slider.value;
// 计算初始动量和动能
const m1 = parseFloat(m1Slider.value);
const m2 = parseFloat(m2Slider.value);
const v1 = parseFloat(v1Slider.value);
const v2 = parseFloat(v2Slider.value);
const p = m1 * v1 + m2 * v2;
const k = 0.5 * m1 * v1 * v1 + 0.5 * m2 * v2 * v2;
pBefore.textContent = p.toFixed(2);
kBefore.textContent = k.toFixed(2);
}
// 计算弹性碰撞后的速度
function calculateCollision() {
const m1 = parseFloat(m1Slider.value);
const m2 = parseFloat(m2Slider.value);
const v1 = parseFloat(v1Slider.value);
const v2 = parseFloat(v2Slider.value);
// 弹性碰撞公式
const v1f = ((m1 - m2) * v1 + 2 * m2 * v2) / (m1 + m2);
const v2f = ((m2 - m1) * v2 + 2 * m1 * v1) / (m1 + m2);
v1After.textContent = v1f.toFixed(2);
v2After.textContent = v2f.toFixed(2);
// 计算碰撞后动量和动能
const p = m1 * v1f + m2 * v2f;
const k = 0.5 * m1 * v1f * v1f + 0.5 * m2 * v2f * v2f;
pAfter.textContent = p.toFixed(2);
kAfter.textContent = k.toFixed(2);
return { v1f, v2f };
}
// 动画函数
function animateCollision() {
const { v1f, v2f } = calculateCollision();
// 重置位置
ball1.style.left = '100px';
ball2.style.left = '400px';
// 获取初始速度
const v1 = parseFloat(v1Slider.value);
const v2 = parseFloat(v2Slider.value);
// 动画参数
let pos1 = 100;
let pos2 = 400;
let collisionHappened = false;
const animationSpeed = 0.5;
function animate() {
// 移动小球1
if (!collisionHappened && pos1 + 25 >= pos2 - 25) {
// 碰撞发生
collisionHappened = true;
pos1 += v1f * animationSpeed;
pos2 += v2f * animationSpeed;
} else if (!collisionHappened) {
// 碰撞前
pos1 += v1 * animationSpeed;
pos2 += v2 * animationSpeed;
} else {
// 碰撞后
pos1 += v1f * animationSpeed;
pos2 += v2f * animationSpeed;
}
ball1.style.left = pos1 + 'px';
ball2.style.left = pos2 + 'px';
// 检查是否超出边界
if (pos1 < -50 || pos1 > 850 || pos2 < -50 || pos2 > 850) {
return;
}
requestAnimationFrame(animate);
}
animate();
}
// 事件监听
m1Slider.addEventListener('input', updateDisplayValues);
m2Slider.addEventListener('input', updateDisplayValues);
v1Slider.addEventListener('input', updateDisplayValues);
v2Slider.addEventListener('input', updateDisplayValues);
startBtn.addEventListener('click', animateCollision);
resetBtn.addEventListener('click', function() {
// 重置滑块
m1Slider.value = 2;
m2Slider.value = 1;
v1Slider.value = 3;
v2Slider.value = 0;
// 重置显示
updateDisplayValues();
// 重置结果
v1After.textContent = '-';
v2After.textContent = '-';
pAfter.textContent = '-';
kAfter.textContent = '-';
// 重置小球位置
ball1.style.left = '100px';
ball2.style.left = '400px';
});
// 初始化
updateDisplayValues();
</script>
</body>
</html>
index.html
style.css
index.js
index.html