運動原理:
對于javascript的運動簡單的來說就是利用定時器讓物體運動起來炒事,并不斷的改變物體的樣式。在運動中我們一般改變的是物體的定位而不是margin值吱七,因為改變margin值有時會影響其他元素容易造成頁面的混亂汽久。也許有的朋友會說難道不能使用for循環(huán)嗎?其實是可以的不過for循環(huán)太快了踊餐,通常你一打開網(wǎng)頁運動就完成了景醇,所以我們一般使用定時器來管理運動。
代碼示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script>
window.onload=function(){
var oT=document.getElementsByTagName('textarea')[0];
var oBtn=document.getElementsByTagName('input')[0];
var oTime=new Date().getTime();//開定時器前先獲取一個時間戳
var timer=setInterval(function(){
var oTime2=new Date().getTime();//根據(jù)定時器的間隔時間再獲取一個時間戳
oT.innerHTML+=oTime2-oTime+'\n';//在文本區(qū)域內(nèi)顯示時間差值
oTime=oTime2;//對初始時間戳重新賦值
},1)
oBtn.onclick=function(){ //暫停鍵
clearInterval(timer);
};
};
</script>
</head>
<body>
<textarea rows="" cols="" id="t1"></textarea>
<input type="button" name="" value="btn">
</body>
</html>
希望各位小伙伴可以在編輯器試一下該段代碼吝岭。
在該段代碼中顯示出一個問題三痰,就是定時器的時間間隔并不是太穩(wěn)定
(ps:你們也看到了飄得很是厲害。窜管。散劫。。)
??在javascript的定時器中選取間隔數(shù)字是有講究的幕帆,一般選擇的運動時間間隔為20-40ms之間,我們平均一下選取30ms获搏。一來人類視覺感受可以接受,時間間隔長會產(chǎn)生鈍感失乾,時間間隔太短的話會對性能的消耗也很大(碰到個辣眼睛的圖片會晃瞎哈哈哈)常熙。我們選取30ms如下圖:
小伙伴們看到了吧,很穩(wěn)定吧碱茁。
??對于定時器在javascript中的運行順序也需要提一下裸卫,計算機在執(zhí)行代碼時會先執(zhí)行定時器下邊的代碼,到了時間才會執(zhí)行定時器里邊的纽竣。
代碼示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script>
var n=1;
setInterval(function(){
n=2;
},1);
alert(n);
</script>
</head>
<body>
</body>
</html>
該代碼顯示的結(jié)果為1墓贿。
??定時器還有一個問題就是當(dāng)你在瀏覽器中打開另外一個頁面時瀏覽器會默認的將你的原來有定時器的那個頁面的時間間隔降為1s以優(yōu)化性能茧泪。
代碼示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script>
var n=0;
setInterval(function(){
n++;
document.title=n;
},1);
</script>
</head>
<body>
</body>
</html>
接下來我們可以試一下物體的運動了。
代碼示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
*{margin: 0;
padding: 0;
list-style: none;}
div{width: 100px;
height: 100px;
background: red;
position: absolute;
left: 0;}
</style>
<script>
window.onload=function(){
var oDiv=document.getElementsByTagName('div')[0];
var time=1000;//總時間;
var start=0;//開始
var end=300;//結(jié)束
var dis=end-start;//總位置
var count=Math.ceil(time/30);//次數(shù)
var n=0;//統(tǒng)計步數(shù)聋袋;
var timer=null;
timer=setInterval(function(){
n++;
oDiv.style.left=n*dis/count+'px';//n*一步距離队伟;
oDiv.style.top=n*dis/count+'px';//n*一步距離;
if(n==count){
clearInterval(timer);
}
},30);
}
</script>
</head>
<body>
<div></div>
</body>
</html>
在以上代碼我們首先要設(shè)定好的就是總時間舱馅、開始位置缰泡、目標(biāo)位置刀荒、總路程代嗤、多長時間走一步(其實就是定時器設(shè)置的時間)、一共走多少步count(總時間除以設(shè)置時間: time/設(shè)置時間缠借。其中取整有幾種方式:parseInt\Math.floor()\Math.ceil()\Math.round() )干毅、一步走多遠:dis/count。
??在完成以上目標(biāo)后我們可以繼續(xù)加一些別的東西泼返,比如將以上的代碼進行封裝硝逢。
代碼示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
*{margin: 0;
padding: 0;
list-style: none;}
div{width: 100px;
height: 100px;
background: red;
position: absolute;
left: 100px;
top: 0;}
</style>
<script>
function move(obj,end){
var time=1000;//總時間;
var start=obj.offsetLeft;//開始(在這里初試位置為left:100px)
//注銷var end=300;//結(jié)束
var dis=end-start;//總位置
var count=Math.ceil(time/30);//次數(shù)
var n=0;//統(tǒng)計步數(shù);
var timer=null;
timer=setInterval(function(){
n++;
obj.style.left=start+n*dis/count+'px';//n*一步距離绅喉;
if(n==count){
clearInterval(timer);
}
},30);
}
window.onload=function(){
var oDiv=document.getElementsByTagName('div')[0];
move(oDiv,300);
}
</script>
</head>
<body>
<div></div>
</body>
</html>
以上的代碼除了封裝以外渠鸽,還改變的物體運動的初始位置,各位小伙伴可以敲敲感受一下柴罐。此外我們還可以加上透明度徽缚。
代碼示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
list-style: none;
}
div {
width: 100px;
height: 100px;
background: red;
position: absolute;
left: 100px;
top: 0;
}
</style>
<script>
function getStyle(obj,sName){
return (obj.currentStyle||getComputedStyle(obj,false))[sName]
}
function move(obj, sName,end) {
var time = 1000; //總時間;
var star = parseFloat(getStyle(obj,sName)); //這里用parseFloat取整
//注銷var end=300;//結(jié)束
var dis = end - star; //總位置
var count = Math.ceil(time / 30); //次數(shù)
var n = 0; //統(tǒng)計步數(shù);
var timer = null;
timer = setInterval(function () {
n++;
if(sName=='opacity'){
obj.style[sName] = star + n * dis / count ;
}else{
obj.style[sName] = star + n * dis / count + 'px'; //n*一步距離革屠;
}
if (n == count) {
clearInterval(timer);
}
}, 30);
}
window.onload = function () {
var oDiv = document.getElementsByTagName('div')[0];
move(oDiv,'opacity', 0);
}
</script>
</head>
<body>
<div></div>
</body>
</html>
此為單物體運動凿试,如果多物體還這樣的話就會出現(xiàn)錯誤。在定時器中還有一個問題就是*一定要保證一個物體上有只一個定時器(定時器加載到物體身上以達到互相獨立)似芝。
代碼示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
list-style: none;
}
li{width: 100px;
height: 50px;
background:#6cf;
margin-bottom: 10px;
}
</style>
<script>
function getStyle(obj,sName){
return (obj.currentStyle||getComputedStyle(obj,false))[sName]
}
function move(obj, sName,end) {
var time = 1000; //總時間;
var start = parseFloat(getStyle(obj,sName)); //這里用parseFloat取整
//注銷var end=300;//結(jié)束
var dis = end - start; //總位置
var count = Math.ceil(time / 30); //次數(shù)
var n = 0; //統(tǒng)計步數(shù)那婉;
clearInterval(obj.timer);
obj.timer = setInterval(function () {
n++;
if(sName=='opacity'){
obj.style[sName] = start + n * dis / count ;
}else{
obj.style[sName] = start + n * dis / count + 'px'; //n*一步距離;
}
if (n == count) {
clearInterval(obj.timer);
}
}, 30);
}
window.onload = function () {
var aLi = document.getElementsByTagName('li');
for(var i=0;i<aLi.length;i++){
aLi[i].onmouseover=function(){
move(this,'width',400);
}
aLi[i].onmouseout=function(){
move(this,'width',100);
}
}
}
</script>
</head>
<body>
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</body>
</html>
千萬記住要清定時器党瓮。详炬。否則他會一直動哈哈。而且事件之間也會起沖突寞奸。
??大家肯定對于上邊那個關(guān)于透明度的問題有疑問呛谜,我除了設(shè)定透明度還要設(shè)置寬度怎么辦呢,原來的數(shù)據(jù)被透明度給占據(jù)了蝇闭。這里就由json出場了呻率。將相對應(yīng)的需要獲取的鍵值加入for in循環(huán)
代碼示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
list-style: none;
}
div {
width: 100px;
height: 100px;
background: red;
position: absolute;
left: 100px;
top: 0;
}
</style>
<script>
function getStyle(obj, sName) {
return (obj.currentStyle || getComputedStyle(obj, false))[sName]
}
//function move(obj, sName,end) {原來的替換為下邊這個
function move(obj, json) {
var time = 1000; //總時間;
var start = {} //{width:0;height:0;}開始位置{left:0,top:0}
var dis = {} //{width:300;height:300;}總距離{left:300呻引,top:300}
for (var name in json) {
start[name] = parseFloat(getStyle(obj, name)); //
dis[name] = json[name] - start[name];
console.log(start);
console.log(dis)
}
var count = Math.ceil(time / 30); //次數(shù)
var n = 0; //統(tǒng)計步數(shù)礼仗;
clearInterval(obj.timer);
obj.timer = setInterval(function () {
n++;
for (var name in json) {
if (name == 'opacity') {
obj.style[name] = start[name] + n * dis[name] / count;
} else {
obj.style[name] = start[name] + n * dis[name] / count + 'px'; //n*一步距離;
}
}
if (n == count) {
clearInterval(obj.timer);
}
}, 30);
}
window.onload = function () {
var oDiv = document.getElementsByTagName('div')[0];
document.onclick = function () {
move(oDiv, {
'width': 300,
'height': 300,
'opacity': 0
});
};
}
</script>
</head>
<body>
<div></div>
</body>
</html>
已經(jīng)為大家加入了console.log大家可以看一下start與end的json的鍵值對。
在此基礎(chǔ)上我們可以進一步升級元践,加入控制時間選項韭脊。
代碼示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
list-style: none;
}
div {
width: 100px;
height: 100px;
background: red;
position: absolute;
left: 100px;
top: 0;
}
</style>
<script>
function getStyle(obj, sName) {
return (obj.currentStyle || getComputedStyle(obj, false))[sName]
}
//function move(obj, sName,end) {
function move(obj, json,duration,complete) {
var time=duration||1000;//前者條件滿足就不往后走了,或的條件
var start = {} //{width:0;height:0;}開始位置{left:0单旁,top:0}
var dis = {} //{width:300;height:300;}總距離{left:300沪羔,top:300}
for (var name in json) {
start[name] = parseFloat(getStyle(obj, name)); //
dis[name] = json[name] - start[name];
// console.log(start);
// console.log(dis)
}
var count = Math.ceil(time / 30); //次數(shù)
var n = 0; //統(tǒng)計步數(shù);
clearInterval(obj.timer);
obj.timer = setInterval(function () {
n++;
for (var name in json) {
if (name == 'opacity') {
obj.style[name] = start[name] + n * dis[name] / count;
} else {
obj.style[name] = start[name] + n * dis[name] / count + 'px'; //n*一步距離象浑;
}
}
if (n == count) {
clearInterval(obj.timer);
complete && complete();//如果有就執(zhí)行如果沒有就不執(zhí)行蔫饰,防止了無函數(shù)出現(xiàn)undefine。
}
}, 30);
}
window.onload = function () {
var oDiv = document.getElementsByTagName('div')[0];
document.onclick = function () {
move(oDiv, {
'width': 300,
'height': 300,
'opacity': 0
},3000,function(){
alert(1);
});
};
}
</script>
</head>
<body>
<div></div>
</body>
</html>
我們將控制時間與完成時執(zhí)行事件封裝愉豺。
示例代碼:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
list-style: none;
}
div {
width: 100px;
height: 100px;
background: red;
position: absolute;
left: 100px;
top: 0;
}
</style>
<script>
function getStyle(obj, sName) {
return (obj.currentStyle || getComputedStyle(obj, false))[sName]
}
//function move(obj, sName,end) {
function move(obj, json,options) {
//var time = 1000; //總時間;
var options=options||{};
var time=options.duration||1000;//前者條件滿足就不往后走了篓吁,或的條件
var start = {} //{width:0;height:0;}開始位置{left:0,top:0}
var dis = {} //{width:300;height:300;}總距離{left:300蚪拦,top:300}
for (var name in json) {
start[name] = parseFloat(getStyle(obj, name)); //
dis[name] = json[name] - start[name];
// console.log(start);
// console.log(dis)
}
var count = Math.ceil(time / 30); //次數(shù)
var n = 0; //統(tǒng)計步數(shù)杖剪;
clearInterval(obj.timer);
obj.timer = setInterval(function () {
n++;
for (var name in json) {
if (name == 'opacity') {
obj.style[name] = start[name] + n * dis[name] / count;
} else {
obj.style[name] = start[name] + n * dis[name] / count + 'px'; //n*一步距離;
}
}
if (n == count) {
clearInterval(obj.timer);
options.complete && options.complete();//如果有就執(zhí)行如果沒有就不執(zhí)行驰贷,防止了無函數(shù)出現(xiàn)undefine盛嘿。
}
}, 30);
}
window.onload = function () {
var oDiv = document.getElementsByTagName('div')[0];
document.onclick = function () {
move(oDiv, {
"width": 300,
"height": 300,
"opacity": 0
},{"duration":3000,"complete":function(){
alert(1);
}});
};
}
</script>
</head>
<body>
<div></div>
</body>
</html>
到這里對于運動方面就告一段落了,在工作中我們都會使用已經(jīng)封裝好的框架來用括袒,以上內(nèi)容就是為了更好的理解javascript運動的邏輯問題次兆。
本人前端小白,希望在自己努力的同時可以認識更多志同道合的朋友箱熬,也希望大神和老師傅們能夠提攜一二帶我上車类垦,本人不勝感激。哈哈城须,希望小伙伴們能夠給出意見蚤认,讓我能夠加以改正,謝謝糕伐!