1. 程式人生 > >JS運動

JS運動

數字 ons compute for 物體 想要 getc 步驟 meta

新學的JS運動,和各位分享一下。

提到運動,肯定要對元素進行定位,通過更改它的left,top值來實現定位的目的,運動過程用定時器來實現。

基本步驟:

  1.關閉上一個定時器(多次觸發事件會開啟多個定時器,會累加)

  2.開啟一個定時器

  3.定義一個值作為運動的速度

  4.判斷定時器什麽時候關閉,也就是終止條件

  5.讓元素怎樣動

下面開始說幾種常見的運動

1.勻速運動

速度是不變的。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
*{margin:0;padding:0;}
#box{
width: 100px;
height: 100px;
background: red;
position: absolute;
}
</style>
</head>
<body>
<div id="box"></div>
</body>
</html>
<script>
var oBox = document.getElementById("box");
var speed = 10;

var timer=null;
document.onclick = function () {
timer= setInterval(function(){

  if(oBox.offsetLeft>=400){

    clearInterval(timer);

  }else{

     oBox.style.left = oBox.offsetLeft+speed+"px";

  }

},30)
}
</script>

oBox會勻速向右運動400px後停止,建議終止條件寫oBox.offsetLeft>=400,而不是oBox.offsetLeft==400,因為定時器每次加一個speed,不一定正好加到所給的終止值。

以下案例的布局是一樣的,所以只寫JS代碼

2.減速運動

<script>
var oBox = document.getElementById("box");
var speed = 40;
var timer=null;
document.onclick = function () {
timer= setInterval(function(){
speed--;
if(speed<0){
speed=0;
}
console.log();
  if(oBox.offsetLeft>=800){

    clearInterval(timer);

  }else{

     oBox.style.left = oBox.offsetLeft+speed+"px";

  }

},30)
}
</script>

速度每次減減,加速度相同,所以是勻減速運動

3.勻加速運動(同理)

<script>
var oBox = document.getElementById("box");
var speed = 5;
var timer=null;
document.onclick = function () {
timer= setInterval(function(){
speed++;
if(speed>=40){
speed=40;
}
  if(oBox.offsetLeft>=800){

    clearInterval(timer);

  }else{

     oBox.style.left = oBox.offsetLeft+speed+"px";

  }

},30)
}
</script>

4.緩沖運動 (樣式改變)

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
*{margin:0;padding:0;}
#box{
width: 100px;
height: 100px;
background: red;
position: absolute;
left: 800px;
}

#border{
width: 1px;
height: 300px;
background: #000;
position: absolute;
left: 400px;
top: 0;
}
</style>
</head>
<body>
<div id="box"></div>
<div id="border"></div>
</body>
</html>

<script>

var oBox = document.getElementById("box");
var timer = null;

document.onclick=function(){
clearInterval(timer);
timer=setInterval(function(){
var speed=(400-oBox.offsetLeft)/8;
speed=speed>0?Math.ceil(speed):Math.floor(speed);
console.log(speed);
if(oBox.offsetLeft==400){
clearInterval(timer);
}else{
oBox.style.left=oBox.offsetLeft+speed+"px";
}
},30);
}

</script>

每次都把速度的值變小,但不是均勻的改變(跟減速運動最大不同),取整是為了讓瀏覽器更好的計算,避免計算小數,以免出現誤差。

封裝一下。

function move(obj,iTarget){
clearInterval(timer);
timer = setInterval(function(){
//速度
var speed = (iTarget - obj.offsetLeft)/8;
speed = speed>0?Math.ceil(speed):Math.floor(speed);

if(obj.offsetLeft==iTarget){
clearInterval(timer)
}else{
obj.style.left = obj.offsetLeft+speed+"px";
}

},30)
}

obj,是對象,iTarget是目標值。例如:move(div,400)

5.上面的封裝不完善,想改變一個元素的透明度就做不到。透明度是小數且沒單位,還得做IE的兼容,下面是怎樣更改透明度

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
*{margin:0;padding:0;}
#box{
width: 100px;
height: 100px;
background: red;
opacity: 1;
filter: alpha(opacity: 100);

}
</style>
</head>
<body>
<div id="box"></div>
</body>
</html>
<script>
var oBox = document.getElementById("box");
var timer =null;
var alpha = 100;

document.onclick=function(){
clearInterval(timer);
timer=setInterval(function(){
var speed=(30-alpha)/8;
speed=speed>0?Math.ceil(speed):Math.floor(speed);
if(alpha==30){
clearInterval(timer);
}else{
alpha+=speed;
oBox.style.opacity=alpha/100;
oBox.style.filter="alpha(opacity:"+alpha+")";
}
},30);
}
</script>

6.考慮到透明度,於是再次封裝。

這次先封裝一個獲取非行內元素

function getStyle(obj,attr){

return obj.currentStyle?obj.currentStyle[attr]:getComputedStyle(obj,false)[attr];

}

function move(obj,target,attr){
clearInterval(timer);
timer=setInterval(function(){
var icur=0;
if(attr=="opacity"){
//避免opacity的值是0.5555555這樣,所以取整
icur=parseInt(getStyle(obj,attr)*100);
}else{
icur=parseInt(getStyle(obj,attr));
}

var speed=(target-icur)/8;
speed=speed>0?Math.ceil(speed):Math.floor(speed);

if(icur==target){
clearInterval(timer);
}else{
if(attr=="opacity"){
obj.style.opacity=(icur+speed)/100;
obj.style.filter="alpha(opacity:"+(icur+speed)+")";
}else{
obj.style[attr]=icur+speed+"px";
}
}
},30);
}

oBox.onmouseover = function(){
move(this,100,"opacity");
}

調用一下,沒問題

7.多物體運動框架

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
*{margin:0;padding:0;}
div{
width: 100px;
height: 100px;
background: red;
opacity: 0.3;
filter: alpha(opacity: 30);
margin: 10px;
}
</style>
</head>
<body>
<div></div>
<div></div>
<div></div>
</body>
</html>
<script>
function getStyle(obj,attr){
if(obj.currentStyle){
return obj.currentStyle[attr];
}else{
return getComputedStyle(obj,false)[attr];
}
}


function move(obj,iTarget,attr){
//obj.timer,定時器之間不影響
clearInterval(obj.timer);
obj.timer = setInterval(function(){
//第一步 判斷attr是否為透明度
var iCur = 0;
if(attr == "opacity"){
iCur =parseInt(getStyle(obj,attr)*100);
}else{
iCur = parseInt(getStyle(obj,attr));
}

//第二步算速度
var speed = (iTarget - iCur )/8;
speed = speed>0?Math.ceil(speed):Math.floor(speed);


//第三步
if(iCur == iTarget){
clearInterval(obj.timer);
}else{
if(attr == "opacity"){
obj.style.opacity = (iCur+speed)/100;
obj.style.filter = "alpha(opacity:"+(iCur+speed)+")";
}else{
obj.style[attr] = iCur+speed+"px";
}

}


},30)
}

var aDiv = document.getElementsByTagName("div");

aDiv[0].onmouseover = function(){
move(this,300,"width")

}

aDiv[1].onmouseover = function(){
move(this,300,"height")
}

aDiv[2].onmouseover = function(){
move(this,100,"opacity")
}
</script>

當多物體的時候,只用一個timer定義定時器時,會影響下一個物體的運動,所以要用obj.timer,關閉的時候關閉自己的定時器,不影響其他定時器的執行

8.鏈式運動

function getStyle(obj,attr){
if(obj.currentStyle){
return obj.currentStyle[attr];
}else{
return getComputedStyle(obj,false)[attr];
}
}


function move(obj,iTarget,attr,fn){
clearInterval(obj.timer);
obj.timer = setInterval(function(){
//第一步 判斷attr是否為透明度
var iCur = 0;
if(attr == "opacity"){
iCur =parseInt(getStyle(obj,attr)*100);
}else{
iCur = parseInt(getStyle(obj,attr));
}

//第二步算速度
var speed = (iTarget - iCur )/8;
speed = speed>0?Math.ceil(speed):Math.floor(speed);


//第三步
if(iCur == iTarget){
clearInterval(obj.timer);
fn&&fn();
}else{
if(attr == "opacity"){
obj.style.opacity = (iCur+speed)/100;
obj.style.filter = "alpha(opacity:"+(iCur+speed)+")";

}else{
obj.style[attr] = iCur+speed+"px";
}

}


},30)
}

var aDiv = document.getElementsByTagName("div");

aDiv[0].onmouseover = function(){
move(this,100,"opacity",function(){
move(aDiv[0],300,"height");
})

}
//給2個move(),下面會覆蓋上面的函數,再寫一個事件,也不行
aDiv[1].onmouseover = function(){
move(this,300,"height")
}

aDiv[2].onmouseover = function(){
move(this,100,"opacity")
}

給原來封裝的函數加一個回調函數,解決

9.完美運動(讓元素2個屬性同時運動,鏈式運動只能一個執行完,再執行另一個)

<script>
function getStyle(obj,attr){
if(obj.currentStyle){
return obj.currentStyle[attr];
}else{
return getComputedStyle(obj,false)[attr];
}
}
//obj={width:100,height:200}

function move(obj,json,fn){
//防止多次點擊 關閉掉上一個定時器
clearInterval(obj.timer);
//開啟定時器 obj.timer:防止多個對象搶定時器
obj.timer = setInterval(function(){
//開關門
var bStop = true;
//傳入的是一個對象 需要將對象中所有的值進行遍歷
for(var attr in json){
/*
因為offset的局限性太大,如果想要這個方法靈活多用只能用獲取非行間樣式

考慮2點
1、透明度是小數 不能夠直接取整需要先*100在取整

2、因為getStyle()獲取出來的是字符串 我們需要將它轉換為數字
*/
var iCur = 0;
if(attr == "opacity"){
iCur = parseInt(getStyle(obj,attr)*100);
}else{
iCur = parseInt(getStyle(obj,attr));
}



/*
因為要做緩存運動,因此需要計算速度 速度是一個不定值
公式: (目標值 - 當前對象的位置) /系數 建議是8

考慮的問題:
計算機處理小數有問題因此需要將小數幹掉,我們要進行向上取整和向下取整
*/
//算速度
var speed = (json[attr] - iCur)/8;
speed = speed>0?Math.ceil(speed):Math.floor(speed);

/*判斷是否都已經到達終點 只要有一個沒有到達終點就將bStop為false 循環完畢以後判斷bstop來決定關閉定時器*/
if(json[attr] !=iCur){
bStop = false;
}


/*
考慮2部分
1、透明度是不需要加px的因此需要單獨判斷
2、普通的屬性是需要加px的因此需要再次判斷

*/
if(attr == "opacity"){
//透明度的兼容性
obj.style.opacity = (iCur+speed)/100;
obj.style.filter = "alpha(opacity:"+(iCur+speed)+")";
}else{
obj.style[attr] = (iCur+speed)+"px";
}


}

//當循環完畢以後 判斷bStop的狀態來決定是否關閉定時器
if(bStop){
clearInterval(obj.timer);
//鏈式操作
fn&&fn();
}

},30)
}

var aDiv = document.getElementsByTagName("div");

aDiv[0].onmouseover = function(){
move(this,{width:300,height:150},function(){
move(aDiv[0],{opacity:100});
});
}

JS運動