平抛运动交互课件
平抛运动可能是物理交互性课件中必做的一个内容,近 20 年前用 flash 做过一个,那时还是看《电脑报》上的教程学会的,不过现在连源码都找不到了。
这次要实现的是沪科版必修二第五章 第二节 平抛运动中的图 5–16,如下图所示。
做出的成品如下所示:
用 svg 绘制函数曲线的基本思路
数学函数是无限连续的,而计算机屏幕是由有限个像素点组成的离散世界。连续函数就像真实世界中的公路——它是连续、光滑、无限精细的,SVG 路径就像 GPS 为你规划的导航路线——它是由有限个关键点(航路点)连接而成的折线。
例如要绘制 y = sin(x) 的函数图像的具体操作步骤如下:
1.确定采样范围:比如在 x = [− π,π] 之间绘制。
2.决定采用点数量,比方说 1000。采样点太少曲线会出现锯齿,不够光滑;采样点太多计算量大,文件体积大;经验法则是相邻两点在屏幕上距离不超过 1 ~ 2 像素为宜。
3.计算每个点的坐标:
- x1 = − π,y1 = sin(− π) = 0 → SVG 点 (x1,y1)
- x2 = − π + 2π/999,y2 = sin(π + 2π/999) → SVG 点 (x2,y2)
- ……
- 第 1000 个点:x1000 = π,y1000 = sin(π) = 0 → SVG 点 (x1000,y1000) 连接离散点
4.有了一系列离散点,需要像珍珠那样用“线”把它们穿起来。在 SVG 中,这是通过 <path> 元素的“d”属性实现的。
假设我们有 3 个点:P1(100,200)2,P2(300,150),P3(500,250),步骤如下:
(1)移动到起点:M 100 200。M 是“Move to”的缩写,相当于把笔尖放到纸上起点处。
(2)画直线到第二点:L 300 150。L 是“Line to”的缩写,从当前位置画直线到这个点。
(3)画直线到第三点:L 500 250。继续用直线连接。
完整路径字符串:“M 100 200 L 300 150 L 500 250”
绘制抛物线轨迹的代码如下:
// 绘制轨迹
function drawTrajectory() {
// 确保必要的物理参数有效
const validScale = state.scale > 0 ? state.scale : 10;
const originX = CONSTANTS.ORIGIN_X;
const originY = CONSTANTS.ORIGIN_Y;
const scale = validScale;
const steps = CONSTANTS.TRAJECTORY_STEPS; // 轨迹点数量,设置为55
const dt = CONSTANTS.MAX_TIME / steps; // CONSTANTS.MAX_TIMEs设置为 3 秒
let path = `M ${originX} ${originY}`;
for (let i = 1; i <= steps; i++) {
const t = i * dt;
const pos = calculatePosition(t);
const x = originX + pos.x * scale;
const y = originY + pos.y * scale;
// 如果y坐标超过最大允许像素值,停止绘制
if (y > CONSTANTS.Y_MAX_PIXEL) {
break;
}
path += ` L ${x} ${y}`;
}
elements.trajectoryPath.setAttribute('d', path);
}
// 计算平抛运动的位置
function calculatePosition(t) {
// 确保时间值有效
const validT = isFinite(t) && t >= 0 ? t : 0;
// 确保物理参数有效
const validV0 = state.v0 >= 1 ? state.v0 : 1;
const validG = state.g > 0 ? state.g : 10;
const x = validV0 * validT;
const y = 0.5 * validG * validT * validT;
// 确保返回的坐标值有效
return {
x: isFinite(x) ? x : 0,
y: isFinite(y) ? y : 0
};
}
在 600 像素见方的范围内只取了 55 个采样点,但画出的图线已经足够光滑了。calculatePosition(t) 方法 AI 写得有点啰嗦,但它说:从用户界面角度:这些检查不是必需的,因为输入已经被严格限制;从代码健壮性角度 :保留这些检查是有益的,可以增强代码的可靠性;从实际使用角度:这些检查不会造成明显的性能问题。
简化的代码可写成:
// 计算平抛运动的位置
function calculatePosition(t) {
const x = state.v0 * t;
const y = 0.5 * state.g * t * t;
return {
x,
y
};
}
数学公式在页面上的显示
在页面上出现了带有分数、根号的数学公式,但为寥寥几个公式而引入 MathJax 或 Katex 库没有必要,方法是将公式转换为 svg 图形,然后将它们插入页面的对应位置。我采用的是在线转换工具:Codecogs Equation Editor。
完整代码
发布时间:2026/1/5 上午10:38:22 阅读次数:246
