先進行一個簡單的方向運動
此網頁主要實現對一個dom元素的運動方向控制及運動狀態控制
HTML主要代碼如下:
<div id="obj"></div>
<button>tUp</button>
<button>tRight</button>
<button>tDown</button>
<button>tLeft</button>
<button>Quicker</button>
<button>Slower</button>
<button>Stop</button>
JS主要代碼如下:
//獲取運動目標元素,並初始化其樣式
var obj = document.getElementById("obj");
obj.style.position = "absolute";
obj.style.height = "20px";
obj.style.width = "20px";
obj.style.borderRadius = "50%";
obj.style.background = "skyblue";
//獲取按鈕
var btn = document.getElementsByTagName("button");
//初速度
var speedX = 5, speedY = 5;
//設置定時器,實現運動
obj.t = setInterval( function() {//將該定時器設為obj專屬
obj.style.left = obj.offsetLeft + speedX + "px";
obj.style.top = obj.offsetTop + speedY + "px";
//觸碰邊界時反彈
if ( ( ( document.body.offsetWidth - obj.offsetLeft ) < obj.offsetWidth ) || obj.offsetLeft <= 0 ) {
speedX *= -1;
}
if ( ( ( document.body.offsetHeight - obj.offsetTop ) < obj.offsetHeight ) || obj.offsetTop <= 0 ) {
speedY *= -1;
}
}, 30);
//按鈕控制方向
for ( var i = 0; i < btn.length; i ++ ) {
btn[i].dire = i;
btn[i].onclick = function() {
switch( btn[i].dire ) {
case 0: speedY = -Math.abs( speedY ); break;
case 1: speedX = Math.abs( speedX ); break;
case 2: speedY = Math.abs( speedY ); break;
case 3: speedX = -Math.abs( speedX ); break;
case 4: speedX = speedX > 0 ? ++speedX : --speedX; speedY = speedY > 0 ? ++speedY : --speedY; break;
case 5: speedX = speedX > 0 ? --speedX : ( speedX == 0 ? 0 : ++speedX ); speedY = speedY > 0 ? --speedY : ( speedY == 0 ? 0 : ++speedY ); break;
case 4: speedX = 0; speedY = 0;
}
}
}
然后是拋物線運動
拋物線運動的軌跡需要進行計算,按照拋物線公式ax^x+bx+c=y,我們需要得知a、b、c的值才能得知這個軌跡,這樣看起來難以馬上得知,但通過一點技巧就不同了。
對於a、b、c三個參數,a代表曲率,在沒有要求的情況下可以自行設定,因為不管如何的曲率,配合某個b的值都能到達目的坐標;而c就更容易去掉了,c代表拋物線的偏移,如果我們將起點作為坐標系起點,c的值就可以直接忽略了。
html主要代碼如下:
<div id="ball"></div>
<div id="target"></div>
一點簡單的css樣式:
#ball {
height: 20px;
width: 20px;
background: brown;
border-radius: 50%;
position: absolute;
left: 10px;
top: 400px;
}
#target {
height: 20px;
width: 20px;
background: skyblue;
position: absolute;
right: 300px;
top: 100px;
opacity: 0.6;
}
JS主要代碼:
var ball = document.getElementById("ball");
//目標位置
var target = {
X : document.getElementById("target").offsetLeft,
Y : document.getElementById("target").offsetTop
}
//將起點定義為圓心
var centerPoint = {
X : ball.offsetLeft,
Y : ball.offsetTop
}
//"圓心"坐標
var x = centerPoint.X, y = centerPoint.Y;
//拋物線公式參數
var a = 0.0008; //曲率,若無要求,自己定義就行了
var b = ( target.Y - a*target.X*target.X ) / target.X;//根據目的坐標和a來計算b的值,因為起點位置已經被作圓心,而a是相對於這個圓心的,所以不能帶入起點坐標進行計算
ball.t = setInterval( function() {
x++;//橫坐標遞增
ball.style.left = x + centerPoint.X + "px";
ball.style.top = a*x*x + b*x + centerPoint.Y + "px";
if ( ball.offsetLeft >= document.getElementById("target").offsetLeft ) {
clearInterval( timer );
}
}), 1);
最后一個示例,緩沖運動
其實緩沖運動的原理也很簡單,其基本思路是將加速度與速度的關系轉換成每次運動的步長——比如第一次運動的步長為距離的五分之一,本次運動完成后步長又為剩下距離的五分之一,以此類推。這里的步長就相當於單位時間里運動的距離,即速度。但是在邏輯上這個方法是不可能到達終點的(芝諾悖論)。所以在步長某次計算后需要進行約束,不再讓它改變,這個值在計算機來看為1像素是再好不過了。所以當步長小於1的時候我們可以將其約束為1。
html主要代碼:
<div id="ball"></div>
css樣式:
#ball {
height: 20px;
width: 20px;
background: #f00;
position: absolute;
top: 200px;
left: 100px;
border-radius: 50%;
}
JS主要代碼:
var ball = document.getElementById("ball")
var distance = 800; //設置移動的距離為800
ball.t = setInterval( function() {
var speed = ( ( distance - ball.offsetLeft ) / 8 ) < 1 ? 1 : ( ( distance - ball.offsetLeft ) / 8 );//步長每次都為剩下距離的八分之一,當某一次步長小於1時,將其約束為1
obj.style.left = obj.offsetLeft + speed + "px";
if ( obj.offsetLeft == distance ) {
clearInterval( obj.t );
}
}, 30);
預覽:http://htmlpreview.github.io/?https://github.com/shockw4ver/JavaScriptCases/blob/master/JSSports/緩沖運動.html
PS: 這里我是將緩沖運動封裝成了一個函數,可以實現各種屬性的緩沖變換,地址為:https://github.com/shockw4ver/JavaScriptCases/blob/master/js lib/move.js
其中還需要一個getCount函數在:https://github.com/shockw4ver/JavaScriptCases/blob/master/js lib/getNodes.js
三種比較典型的運動就在這里啦!
Thanks for Read!