本文详细介绍如何使用JavaScript模拟物体的自由落体与上抛运动。通过封装类管理状态,利用定时器更新位移与速度,结合重力加速度公式计算轨迹,并引入阻尼系数模拟真实阻力效果,最终实现点击页面生成方块并展示完整运动过程。
本文通过具体实例,详细解析了利用JavaScript实现自由落体与上抛运动模拟的原理及代码实现方法,旨在为相关开发者提供参考与学习素材。
JavaScript 代码
//****************************************
//名称:Javascript摸拟自由落体与上抛运动!
//作者:Gloot
//邮箱:glootz@gmail.com
// QQ:345268267
//网站:http://www.cnblogs.com/editor/
//操作:在页面不同地方点几下
//***************************************
var $ = function(el) { return document.getElementById(el); };
function LuoRun()
{
this.h = 0;
this.s = 0;
this.g = 9.8;
this.isup = false;
this.rh = 0;
this.t = 0;
this.timer = null;
this.mt = 0;
this.top = 0;
this.left = 0;
this.id = null;
}
LuoRun.prototype.Po = function(obj) {
this.left += 0.3;
obj.style.left = (this.left)+'px';
if (!this.isup) {
if (this.t == 0)
{
this.top = obj.offsetTop;
this.h = 570 - 22 - this.top;
this.mt = Math.sqrt(2*this.h/(this.g*100));
//alert(mt+' '+isup+' '+t)
}
this.t+=0.01;
if (this.t >= this.mt)
{
this.t = this.mt;
this.rh = (1/2)*this.g*this.t*this.t*100;
this.s = this.g*this.t*100;
obj.style.top = (this.rh+this.top)+'px';
//t = 0;
this.s = this.s-50>0 ? this.s-50 : 0;
this.isup = true;
this.t = 0;
}
else
{
this.rh = (1/2)*this.g*this.t*this.t*100;
this.s = this.g*this.t*100;
obj.style.top = (this.rh+this.top)+'px';
}
} else { //up
//return;
if (this.s == 0) {
clearInterval(this.timer);
this.id.parentNode.removeChild(this.id);
return;
}
if (this.t == 0) {
this.h = this.s*this.s/(2*this.g*100);
this.mt = this.s/(this.g*100);
this.top = obj.offsetTop;
//alert(mt+' '+isup+' '+t)
}
this.t+=0.01;
if (this.t>=this.mt) {
this.t = this.mt;
this.rh = this.s*this.t - (1/2)*this.g*this.t*this.t*100;
obj.style.top = (this.top - this.rh)+'px';
this.s = 0;
this.isup = false;
this.t = 0;
}else {
this.rh = this.s*this.t - (1/2)*this.g*this.t*this.t*100;
obj.style.top = (this.top - this.rh)+'px';
}
}
}
LuoRun.prototype.Go = function(obj) {
var self = this;
if (obj == null)
obj = $('box');
self.timer = setInterval(function() {
self.Po(obj);
if (self.h<=0) {
clearInterval(self.timer);
self.id.parentNode.removeChild(self.id);
}
},10);
}
document.onmousedown = function(e) {
e = e?e:window.event;
var crtDiv = document.createElement('div');
crtDiv.style.position = 'absolute';
crtDiv.style.left = e.clientX + 'px';
crtDiv.style.top = e.clientY + 'px';
crtDiv.style.background = '#333';
crtDiv.style.width = '22px';
crtDiv.style.height = '22px';
document.body.appendChild(crtDiv);
crtDiv.innerHTML = ' ';
var C = new LuoRun();
C.left = e.clientX;
C.id = crtDiv;
document.onmouseup = function() {
document.onmousemove = null;
window.setTimeout(function() { C.Go(crtDiv); },1000);
}
}
Css 样式
<style type="text/css">
td,body {font-size:12px;}
.css1 {width:240px;display:table;position:absolute;left:20px;top:20px;border:1px solid green;background:#CAF4BD;line-height:18px;padding:3px;}
.css2 {width:900px;height:22px;border-top:1px solid #333;position:absolute;top:570px;left:60px;}
</style>
Body Html代码
<body>
<form id="form1">
<div class="css1">
名称:Javascript摸拟自由落体与上抛运动!<br />
作者:Gloot<br />
邮箱:glootz@gmail.com <br />
QQ:345268267 <br />
网站:http://www.cnblogs.com/editor/ <br />
操作:在页面不同地方点几下
</div>
<div id="line" class="css2"> </div>
</form>
</body>
代码说明
function JsFunc() {
this.a = "";
this.b = "";
}
JsFunc.prototype.method = function() {
var me = this;
me.a = "method";
}
function init() {
var func = new JsFunc();
func.method();
}
JsFunc 类在功能上类似于C#中的类定义。
var func = new JsFunc();
该步骤相当于完成类的初始化,并实例化创建一个对象。
this.a 与 this.b 对应于类内部的成员变量。
JsFunc.prototype.method 对应于在该类下定义的一个方法函数。
若对 JsFunc 执行多次 new 操作,其下属的 this 成员将各自独立运行,互不干扰。
因此,当对 JsFunc 执行 new 创建新对象后,若对该对象的成员或方法调用 setTimeout 或 setInterval,即可产生类似并行操作的效果。
function LuoRun()
{
this.h = 0;
this.s = 0;
this.g = 9.8;
this.isup = false;
this.rh = 0;
this.t = 0;
this.timer = null;
this.mt = 0;
this.top = 0;
this.left = 0;
this.id = null;
}
this.s 用于表示物体的速度。
this.h 用于表示设定的高度,或物体上抛所能达到的最高高度。
this.isup 用于标识物体当前正处于上升阶段还是下降阶段。
this.rn 用于表示下降时距离当前顶点的位移,或上抛时距离初始速度位置的位移。
this.t 用于记录下降或上抛过程所经历的时间。
this.mt 用于表示从某一高度落体至指定低点所用的时间,或以某一初始速度上抛至速度为零所需的时间。
this.timer 用于存储定时器实例。
this.top 与 this.left 分别表示物体相对于容器顶部及左侧的当前偏移量。
this.id 用于标识当前创建方块的对象ID值。
LuoRun.prototype.Po = function(obj) {
}
此部分定义了物体执行自由落体及上抛运动的核心方法。
this.left += 0.3 表示物体在每次落体或上抛过程中向左跳动的偏移量,单位为像素。
Po 方法是在 setInterval 定时器驱动下执行的动作,每次执行时均根据配置的偏移量以及自由落体与上抛的相关公式计算当前参数变化,并设定物体的位置。
obj.style.left = (this.left)+'px'; 用于初始化当前步骤的左偏移值。
落体状态
if (!this.isup) {...} 用于判断当前是否处于落体状态。
if (this.t == 0)
{
this.top = obj.offsetTop;
this.h = 570 - 22 - this.top;
this.mt = Math.sqrt(2*this.h/(this.g*100));
//alert(mt+' '+isup+' '+t)
}
当时间为 0 时,表示当前处于落体的最顶点,此时记录当前距顶部的偏移值,设定落体的高度,并计算从此高度落体所需的时间。
if (this.t >= this.mt)
{
this.t = this.mt;
this.rh = (1/2)*this.g*this.t*this.t*100;
this.s = this.g*this.t*100;
obj.style.top = (this.rh+this.top)+'px';
//t = 0;
this.s = this.s-50>0 ? this.s-50 : 0;
this.isup = true;
this.t = 0;
}
当落体所用时间大于 this.mt 的最大时间阈值时,将时间强制设置为 this.mt 的落体总时间。
this.rh 根据公式 1/2gt^2 计算得出的位移值,该值将等于或接近 this.h 的高度值。
this.s 根据速度随加速度随时间变化的公式计算出当前速度,此速度即为最大速度,同时也作为初始的上抛速度。
this.s = this.s-50>0 ? this.s-50 : 0; 用于更新速度值。
这里的 50 即为阻尼系数,代表每次上抛过程中因受阻力而减少的速度值。
this.isup 设置为 true,表示物体进入上抛状态。
obj.style.top = (this.rh+this.top)+'px'; 用于设置物体在本步骤落体时的当前位置。
上抛运行
if (this.t == 0) {
this.h = this.s*this.s/(2*this.g*100);
this.mt = this.s/(this.g*100);
this.top = obj.offsetTop;
//alert(mt+' '+isup+' '+t)
}
当时间为 0 时,表示处于上抛开始点,此时根据落体后的速度及公式 v^2/(2g) 计算上升的最大高度 this.h,以及最大上升时间 this.mt,并保存当前距顶部的偏移 this.top。
if (this.t>=this.mt) {
this.t = this.mt;
this.rh = this.s*this.t - (1/2)*this.g*this.t*this.t*100;
obj.style.top = (this.top - this.rh)+'px';
this.s = 0;
this.isup = false;
this.t = 0;
}
当时间 this.t 大于 this.mt 这个最大上抛时间时,将时间设置为 this.mt。
this.rh 表示上抛的高度,计算公式为 vt - (1/2)gt^2。
重置 this.t 及 this.s 的时间与速度,并将 this.isup 置为 false,从而开始落体动作。
LuoRun.prototype.Go = function(obj) {
var self = this;
if (obj == null)
obj = $('box');
self.timer = setInterval(function() {
self.Po(obj);
if (self.h<=0) {
clearInterval(self.timer);
self.id.parentNode.removeChild(self.id);
}
},10);
}
Go 是一个定时器,每 10 毫秒执行一次物体偏移移动操作。
当 this.h 小于等于 0 时,清除物体,表示该对象方块的一个完整落体与上抛过程结束。
document.onmousedown = function(e) {
e = e?e:window.event;
var crtDiv = document.createElement('div');
crtDiv.style.position = 'absolute';
crtDiv.style.left = e.clientX + 'px';
crtDiv.style.top = e.clientY + 'px';
crtDiv.style.background = '#333';
crtDiv.style.width = '22px';
crtDiv.style.height = '22px';
document.body.appendChild(crtDiv);
crtDiv.innerHTML = ' ';
var C = new LuoRun();
C.left = e.clientX;
C.id = crtDiv;
document.onmouseup = function() {
document.onmousemove = null;
window.setTimeout(function() { C.Go(crtDiv); },1000);
}
}
当鼠标点击页面时,创建一个灰黑底色、宽高均为 22 像素的方块。
并初始化(创建新对象)LuoRun 类。
当鼠标松开后,经过一秒钟执行 LuoRun 的 Go 定时器,开始展示物体的落体与上抛过程。
感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.jb51.net/code/HtmlJsRun测试上述代码运行效果。
更多关于JavaScript相关内容感兴趣的读者可查看本站专题:《JavaScript运动效果与技巧汇总》、《JavaScript切换特效与技巧总结》、《JavaScript查找算法技巧总结》、《JavaScript动画特效与技巧汇总》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript数学运算用法总结》
希望本文所述对大家JavaScript程序设计有所帮助。