本文主要為大家帶來一篇打造通用的勻速運動框架(實例講解)。小編覺得蠻不錯的,現在就分享給大家,也給大家做個參考。一起跟著小編過來看看吧,希望能幫助大家。
本文,是接著上基於勻速運動的實例講解(側邊欄,淡入淡出) 繼續的,在這篇文章的最後,我們做了2個小實例:側側邊欄與改變透明度的淡入淡出效果,本文我們把上文的animate函數,繼續改造,讓他變得更加的通用與強大:
1,支援多個物體的運動
2,同時運動
3,順序運動
這三種運動方式也是jquery中animate函數支援的
#一、animate函數中怎麼區分變化不同的樣式?
上文中,側邊欄效果用的animate函數改變的是left值
function animate(obj, target, speed) { clearInterval(timer); timer = setInterval(function () { if (obj.offsetLeft == target) { clearInterval(timer); } else { obj.style.left = obj.offsetLeft + speed + 'px'; } }, 30); }
淡入淡出效果用的animate函數改變的是透明度
function animate(obj, target, speed) { clearInterval(timer); var cur = 0; timer = setInterval(function () { cur = css( obj, 'opacity') * 100; if( cur == target ){ clearInterval( timer ); }else { cur += speed; obj.style.opacity = cur / 100; obj.style.filter = "alpha(opacity:" + cur + ")"; } }, 30); }
而我們封裝的函數,要變成通用的,首先面臨的問題就是這個函數要同時支援left值和透明度的變化,更通用的做法應該是要支援所有的樣式變化,例如輪播功能,他有左右滑動,也有上下滑動。
我們可以在取得樣式和改變樣式的時候,做判斷就好了,判斷分2類就能達到目的,因為其他樣式( margin, left, top, right, font-size等等)都是px,而透明度沒有px單位
function animate(obj, attr, target, speed) { clearInterval(timer); var cur = 0; timer = setInterval(function () { if (attr == 'opacity') { cur = css(obj, 'opacity') * 100; } else { cur = parseInt(css(obj, attr)); } if (cur == target) { clearInterval(timer); } else { if (attr == 'opacity') { obj.style.opacity = ( cur + speed ) / 100; obj.style.filter = "alpha(opacity:" + (cur + speed) + ")"; } else { obj.style[attr] = cur + speed + "px"; } } }, 30); }
合併之後的animate相比之前多了一個參數attr, 這個參數就是變化的樣式,obj: 變化的對象, target: 樣式需要變化到的目標值. speed: 樣式每次變化的大小
如:
oImg.onmouseover = function () { animate(this, 'opacity', 100, 10); }
oImg是獲取到的圖片物件. 這裡各參數意思如下:
this:當前圖片物件
opacity: 變化的樣式是透明度
100: 滑鼠移到圖片上時,透明度變成100
10: 透明度每次在原來的基礎上加10
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>合并的运动 - by ghostwu</title> <style> img { border: none; opacity: 0.3; filter: alpha(opacity:30); position: absolute; left: 200px; } #box { width: 150px; height: 300px; background: red; position: absolute; left: -150px; top: 50px; } #box p { width: 28px; height: 100px; position: absolute; right: -28px; top: 100px; background: green; } </style> <script> window.onload = function () { var oImg = document.getElementById("img"), oBox = document.getElementById("box"), timer = null; oImg.onmouseover = function () { animate(this, 'opacity', 100, 10); } oImg.onmouseout = function () { animate(this, 'opacity', 30, -10); } oBox.onmouseover = function () { animate(this, 'left', 0, 10); } oBox.onmouseout = function () { animate(this, 'left', -150, -10); } function animate(obj, attr, target, speed) { clearInterval(timer); var cur = 0; timer = setInterval(function () { if (attr == 'opacity') { cur = css(obj, 'opacity') * 100; } else { cur = parseInt(css(obj, attr)); } if (cur == target) { clearInterval(timer); } else { if (attr == 'opacity') { obj.style.opacity = ( cur + speed ) / 100; obj.style.filter = "alpha(opacity:" + (cur + speed) + ")"; } else { obj.style[attr] = cur + speed + "px"; } } }, 30); } function css(obj, attr) { if (obj.currentStyle) { return obj.currentStyle[attr]; } else { return getComputedStyle(obj, false)[attr]; } } } </script> </head> <body> <p id="box"> <p>分享到</p> </p> <img src="./img/h4.jpg" alt="" id="img"/> </body> </html>
上述就是完整的程式碼實例。
當你分別測試這兩個功能的時候:
移動到圖片上然後移出來
移動到分享到,然後移出來
#這樣是沒有問題的
如果你這樣測試:
移動到分享到,然後迅速又移動到圖片上, 這個時候你會發現分享到停下來了,這就不符合邏輯了! 照道理來說,滑鼠移動到圖片上,相當於觸發了「分享到」 的mouseout( 滑鼠移出事件),那麼"分享到" 這個時候要隱藏,並不是停止。 為什麼會這樣呢?因為這兩個運動共享了一個定時器,當滑鼠移動到圖片上,開啟定時器的時候,把「分享到」的定時器給停了。那麼再做多物體運動的時候,我們要把定時器拆分,每個物件都要有一個定時器,怎麼做呢? 非常簡單,不要定義一個簡單的timer變量,我們只要把timer加在obj物件上,那麼每個物件都有一個timer屬性,就達到計時器的分離效果了
#修改之後的完整程式碼如下,請自行展開:
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> img { border: none; opacity: 0.3; filter: alpha(opacity:30); position: absolute; left: 200px; } #box { width: 150px; height: 300px; background: red; position: absolute; left: -150px; top: 50px; } #box p { width: 28px; height: 100px; position: absolute; right: -28px; top: 100px; background: green; } </style> <script> window.onload = function () { var oImg = document.getElementById("img"), oBox = document.getElementById("box"); oImg.onmouseover = function () { animate(this, 'opacity', 100, 10); } oImg.onmouseout = function () { animate(this, 'opacity', 30, -10); } oBox.onmouseover = function () { animate(this, 'left', 0, 10); } oBox.onmouseout = function () { animate(this, 'left', -150, -10); } function animate(obj, attr, target, speed) { clearInterval(obj.timer); var cur = 0; obj.timer = setInterval(function () { if (attr == 'opacity') { cur = css(obj, 'opacity') * 100; } else { cur = parseInt(css(obj, attr)); } if (cur == target) { clearInterval(obj.timer); } else { if (attr == 'opacity') { obj.style.opacity = ( cur + speed ) / 100; obj.style.filter = "alpha(opacity:" + (cur + speed) + ")"; } else { obj.style[attr] = cur + speed + "px"; } } }, 30); } function css(obj, attr) { if (obj.currentStyle) { return obj.currentStyle[attr]; } else { return getComputedStyle(obj, false)[attr]; } } } </script> </head> <body> <p id="box"> <p>分享到</p> </p> <img src="./img/h4.jpg" alt="" id="img"/> </body> </html>
至此,我們就完成了多物體運動與不同樣式的修改
##二、讓animate函數支援多個樣式同時改變
例如:
#
oBox.onmouseover = function(){ animate( this, { "width" : 500, "height" : 400 }, 10 ); }oBox是一個p元素,animate各參數的意思:this: 目前p元素{width : 500, "height" : 400 } : 把寬度變成500, 高度變成400,這兩個樣式要在同一時間完成,10: 樣式每次在原來的基礎上變化10(如width初始值200--> 210, 220, 230.....)#完整的同時運動變化代碼:
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> p { width: 200px; height: 200px; background: red; } </style> <script> window.onload = function () { var oBox = document.getElementById("box"); oBox.onmouseover = function(){ // animate( this, { "width" : 500, "height" : 500 }, 10 ); animate( this, { "width" : 500, "height" : 400 }, 10 ); } function animate(obj, attr, speed) { clearInterval(obj.timer); var cur = 0; obj.timer = setInterval(function () { for ( var key in attr ) { if (key == 'opacity') { cur = css(obj, 'opacity') * 100; } else { cur = parseInt(css(obj, key)); } var target = attr[key]; if (cur == target) { clearInterval(obj.timer); } else { if (key == 'opacity') { obj.style.opacity = ( cur + speed ) / 100; obj.style.filter = "alpha(opacity:" + (cur + speed) + ")"; } else { obj.style[key] = cur + speed + "px"; } } } }, 30); } function css(obj, attr) { if (obj.currentStyle) { return obj.currentStyle[attr]; } else { return getComputedStyle(obj, false)[attr]; } } } </script> </head> <body> <p id="box"></p> </body> </html>請自行展開這段程式碼,這段程式碼能夠同時運動,但是有一個問題:p的初始寬度與高度( width : 200, height : 200)變化步長一樣( 10 )變化時間一樣( 每30毫秒變化一次)目標( width: 500, height : 400 )你能想到什麼問題嗎? ( 兩個人在同一起跑線上,速度一樣, 時間一樣,但是要同時到達不同的目標,一個500, 一個400 )答案是很明顯的,肯定是目標近的( height : 400 )那個先到達,然後把物件上的計時器關了,另一個目標更遠的( width: 500 )肯定到達不了你可以在這句程式碼下面,輸出當前的值和目標值:
var target = attr[key]; console.log( key, cur, target );輸出來的結果是:
从上图可以看出,height已经达到了400px,但是width停在了410px,为什么不是400px ? 因为width = 400的时候, 就是( cur == 500 ) 相当于( 400 == 500 ) 不成立,所以执行了else语句,width = cur + 10 = 400 + 10 = 410,然后height到达400px停止了定时器,所以width停在了410px.
那么我们怎么解决这个问题呢?
其实也好办,就是height = 400的时候 不要把定时器关了,应该等width = 500的时候再关闭定时器,不就在同一时间,完成了同时到达目标的效果吗?
修改后的代码如下:
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> p { width: 200px; height: 200px; background: red; } </style> <script> window.onload = function () { var oBox = document.getElementById("box"); oBox.onmouseover = function(){ animate( this, { "width" : 500, "height" : 400 }, 10 ); } function animate(obj, attr, speed) { clearInterval(obj.timer); var cur = 0; obj.timer = setInterval(function () { var bFlag = true; for ( var key in attr ) { if (key == 'opacity') { cur = css(obj, 'opacity') * 100; } else { cur = parseInt(css(obj, key)); } var target = attr[key]; if (cur != target) { bFlag = false; if (key == 'opacity') { obj.style.opacity = ( cur + speed ) / 100; obj.style.filter = "alpha(opacity:" + (cur + speed) + ")"; } else { obj.style[key] = cur + speed + "px"; } } } if ( bFlag ) { clearInterval( obj.timer ); } }, 30); } function css(obj, attr) { if (obj.currentStyle) { return obj.currentStyle[attr]; } else { return getComputedStyle(obj, false)[attr]; } } } </script> </head> <body> <p id="box"></p> </body> </html>
声明一个变量,每次变化完一次( width, height )样式 把bFlag = true, 只要在for循环中有一个没有到达目标,bFlag的值都是false,这样就不会关闭定时器。当两个都到达目标,才关闭定时器.
三、顺序运动
如样式变化,按顺序来,不是同时变化, 如:
oBox.onmouseover = function(){ //回调函数: 把函数当做参数传递给另一个函数 animate( this, { 'width' : 500 }, 10, function(){ animate( this, { 'height' : 500 }, 10 ); } ); }
当把width变成500px的时候,如果传递了回调函数, 再接着执行回调函数里面的运动
修改后的完整代码:
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>通用的匀速运动框架 - by ghostwu</title> <style> p { width: 200px; height: 200px; background: red; } </style> <script> window.onload = function () { var oBox = document.getElementById("box"); oBox.onmouseover = function(){ //回调函数: 把函数当做参数传递给另一个函数 animate( this, { 'width' : 500 }, 10, function(){ animate( this, { 'height' : 500 }, 10 ); } ); } function animate(obj, attr, speed, fn ) { clearInterval(obj.timer); var cur = 0; obj.timer = setInterval(function () { var bFlag = true; for (var key in attr) { if (key == 'opacity') { cur = css(obj, 'opacity') * 100; } else { cur = parseInt(css(obj, key)); } var target = attr[key]; if (cur != target) { bFlag = false; if (key == 'opacity') { obj.style.opacity = ( cur + speed ) / 100; obj.style.filter = "alpha(opacity:" + (cur + speed) + ")"; } else { obj.style[key] = cur + speed + "px"; } } } if (bFlag) { clearInterval(obj.timer); fn && fn.call( obj ); } }, 30); } function css(obj, attr) { if (obj.currentStyle) { return obj.currentStyle[attr]; } else { return getComputedStyle(obj, false)[attr]; } } } </script> </head> <body> <p id="box"></p> </body> </html>
相关推荐:
浅谈Javascript如何实现匀速运动_javascript技巧
以上是通用的等速運動框架如何打造的詳細內容。更多資訊請關注PHP中文網其他相關文章!