JS模拟引力环境下的运动轨迹
话说这篇文章的起源还得从1643年1月4日谈起。这一天,一位引领人类认知世界的巨人诞生了,他就是艾萨克·牛顿(Isaac Newton)。扯远了,就近一点,2010年1月4日,为了纪念牛顿,google设计了一个Google Doodles,看这里:今日google纪念logo-典型的物理运动实现。
进口审核剪切版:
<input type="button" value="demo" onclick="demo()">
<img id="fall" src=http://www.zzsky.cn/build/content/"" style="position:absolute;left:200px;top:46px">
<script type="text/javascript">
function demo(){
var h=1,k=-0.5,f=document.getElementById('fall'),
i=setInterval(function(){
if(f){
var y=parseInt(f.style.top) + h;
if(y<210) {h+=2}
else{
h*=(h>1)?k:0
}
f.style.top=y+'px';
}
if(h==0){clearInterval(i);h=1;}
},25);
}
</script>
随后,我便模拟了一个重力环境下的抛物线运动:
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>模拟重力环境下的抛物运动(假使1px==1mm)</title>
<style type="text/css">
*{padding:0;margin:0;}
html,body{height:100%;overflow:hidden;}
p{margin:2px;font-size:12px;}
label{display:inline-block;width:80px;text-align:right;}
input{width:80px;}
.wrap{position:relative;width:800px;height:500px;margin:5px;border:1px solid #ccc;}
#fall{width:20px;font-size:0;height:20px;background:orange;position:absolute;top:0;left:0;border-radius:10px;-moz-border-radius:10px;-webkit-border-radius:10px;}
</style>
</head>
<body>
<p><label>横向初速度:</label><input id="Vx" type="text" value="3">px/ms</p>
<p><label>纵向初速度:</label><input id="Vy" type="text" value="0">px/ms</p>
<p><label>重力加速度:</label><input id="a" type="text" value="0.0098">px/平方ms</p>
<p>(如果这个加速度是一个随时间变化的值,就能达到其他非匀加速运动的效果了。)</p>
<p><label>单位时间:</label><input id="t" type="text" value="10">(记录运动的时间间隔)
<p><button type="button" onclick="demo()">演示</button></p>
<div class="wrap">
<div id="fall">o</div>
</div>
<script type="text/javascript">
var $id=function(o) {
return document.getElementById(o) || o;
}
var demo=function() {
var x=$id('Vx').value,
y=$id('Vy').value,
a=$id('a').value,
t=$id('t').value;
shoot(x,y,a,t);
}
var shoot=function(x,y,a,t) {
var f=document.getElementById('fall');
var Vx=parseInt(x),
Vy=parseInt(y),
g=a,
t=parseInt(t),
h=0,l=0,Sx=0,Sy=0;
var i=setInterval(function(){
if(f){
Sx+=Vx*t;
l=Sx;
Vy+=g*t;
h+=Vy*t;
if(h>480) {
h=480;
clearInterval(i);
}
if(l>780) {
l=780;
clearInterval(i);
}
f.style.left=l+'px';
f.style.top=h+'px';
}
},t);
}
</script>
</body>
</html>
模拟采用的公式:
Function: 对于运动瞬间
V=V0+aT;
S=S0+VT;
T:运动的时间间隔,是固定值
这个公式有别于那种运动模拟中常用的补间动画公式(tween算法)。补间动画是需要事先确定总路程和总时间的,而我们模拟的运动轨迹没有事先计算,因为我们运动中间或许还有一些变数,比如撞击、主动改变方向(键盘控制)等等,所以我觉得这个物理公式更能模拟出真实的各种运动。
直至本月前两天,某同事向我展示了这个:重力版google(浏览首选chrome、safari,次选opera、firefox,若是ie9以下请无视)。膜拜啊,js且不论,css3已经大量使用了,我还只局限用用阴影、圆角呢。
不才也做一个关于落体、撞击、摩擦的简单模拟,以表膜拜。
[/code]<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>模拟引力环境下的撞击、摩擦、落体运动</title>
<style type="text/css">
*{padding:0;margin:0;}
html,body{height:100%;overflow:hidden;}
p{margin:2px;font-size:12px;}
label{display:inline-block;width:80px;text-align:right;}
input{width:80px;}
#fall{width:20px;font-size:0;height:20px;background:orange;position:absolute;top:50px;left:400px;border-radius:10px;-moz-border-radius:10px;-webkit-border-radius:10px;}
</style>
</head>
<body>
<p><label>横向初速度:</label><input id="Vx" type="text" value="3">px/ms</p>
<p><label>纵向初速度:</label><input id="Vy" type="text" value="0">px/ms</p>
<p><label>重力加速度:</label><input id="a" type="text" value="0.01">px/平方ms</p>
<p><label>单位时间:</label><input id="t" type="text" value="10">(记录运动的时间间隔)
<p>摩擦,碰撞的消耗并没有按公式进行计算,纯属于杜撰,是不符合规律的,仅仅是模拟。</p>
<p><button type="button" onclick="demo()">演示</button><button type="button" onclick="document.location.reload()">重置(可拖动放置)</button></p>
<div id="fall" onmousedown="drag(this,event)">o</div>
</body>
<script type="text/javascript">
var $id=function(o) {
return document.getElementById(o) || o;
}
var demo=function() {
var x=$id('Vx').value,
y=$id('Vy').value,
a=$id('a').value,
t=$id('t').value;
shoot(x,y,a,t);
}
var shoot=function(x,y,a,t) {
if(i) {alert(1);clearInterval(i)};
var f=document.getElementById('fall');
var Vx=parseFloat(x),
Vy=parseFloat(y),
g=parseFloat(a),
h=f.offsetTop,
Sx=f.offsetLeft,
l=0,
t=parseInt(t);
var i=setInterval(function(){
if(f){
Sx+=Vx*t;
l=Sx;
Vy+=g*t;
h+=Vy*t;
if(h>=document.documentElement.offsetHeight-f.offsetHeight) {//底部
h=document.documentElement.offsetHeight-f.offsetHeight;
Vx=(Math.abs(Vx)-0.1 < 0) ? 0 : Vx/Math.abs(Vx) * (Math.abs(Vx)-0.1)//摩擦消耗x速度
Vy=(Math.abs(Vy)-0.8 < 0) ? 0 : -(Math.abs(Vy)-0.8);//撞击消耗y速度
if(Math.abs(Vy)==0 && Math.abs(Vx)==0 ) {clearInterval(i);}//x、y速度为0时,clear
}
if(l<0 || l>document.documentElement.offsetWidth-f.offsetWidth) {//左右两侧
Sx=(l<0) ? 0 : document.documentElement.offsetWidth-f.offsetWidth;
Vx=(Math.abs(Vx)-0.2 < 0) ? 0 : -Vx/Math.abs(Vx) * (Math.abs(Vx)-0.2)//撞击消耗x速度
}
f.style.left=l+'px';
f.style.top=h+'px';
}
},t);
};
var drag=function(o,e){//拖曳位置,与运动模拟无关
var e = e ? e : window.event;
if(!window.event) {e.preventDefault();}
var tX=o.offsetLeft,
tY=o.offsetTop,
dx=e.clientX,
dy=e.clientY;
document.onmousemove=function(e){
var e = e ? e : window.event;
o.style.left=tX+e.clientX-dx+"px";
o.style.top=tY+e.clientY-dy+"px";
}
document.onmouseup=function(){
document.onmousemove=null;
document.onmouseup=null;
}
}
</script>
</html>[/code]
对于这个运动的模拟,我觉得以后倒是可以扩展出一些挺有趣的交互游戏的模拟,比如射击、驾驶等等,当然纯属娱乐啦。
作者:ONEBOYS,原文地址:。