[js高手之路]封裝運動框架實戰左右與上下滑動的焦點輪播圖


在這篇文章[js高手之路]打造通用的勻速運動框架中,封裝了一個勻速運動框架,我們在這個框架的基礎之上,加上緩沖運動效果,然后用運動框架來做幻燈片(上下,左右),效果如下:【選擇器用的是html5的,你的瀏覽器需要支持html5新選擇器,才能看見效果額

 

  • 1
  • 2
  • 3
  • 4
  • 5

 

緩沖運動通常有兩種常見的表現:比如讓一個div從0運動到500,一種是事件觸發的時候,速度很快, 一種是事件觸發的時候慢,然后慢慢加快.我們來實現先塊后慢的,常見的就是開車,比如剛從高速路上下來的車,就是120km/小時,然后進入匝道,變成40km/時.  或者40km/小時進入小區,最后停車,變成0km/小時.  從120km/小時->40km/小時,  或者40km->0km/小時,都是速度先塊后慢,這種運動怎么用程序來表示呢?

可以用目標距離( 500 ) - 當前距離( 200 ) / 一個系數( 比如12 ),就能達到速度由塊而慢的變化,當前距離在起點,分子(500 - 0 )最大,所以速度最大,如果當前距離快要接近500,分子最小,除完之后的速度也是最小。

 1     <style>
 2         div{
 3             width: 200px;
 4             height: 200px;
 5             background:red;
 6             position: absolute;
 7             left: 0px;
 8         }
 9     </style>
10     <script>
11         window.onload = function(){
12             var oBtn = document.querySelector( "input" ),
13                 oBox = document.querySelector( '#box' ),
14                 speed = 0, timer = null;
15             oBtn.onclick = function(){
16                 timer = setInterval( function(){
17                     speed = ( 500 - oBox.offsetLeft ) / 8;
18                     oBox.style.left = oBox.offsetLeft + speed + 'px';
19                 }, 30 );
20             }
21         }
22     </script>
23 </head>
24 <body>
25     <input type="button" value="動起來">
26     <div id="box"></div>
27 </body>

 

 
 
但是,div並不會乖乖地停止在500px這個目標位置,最終卻是停在497.375px,只要查看當前的速度,當前的值就知道原因了

 

 

你會發現,速度永遠都在0.375這里停着,獲取到的當前的距離停在497px? 這里有個問題,我們的div不是停在497.375px嗎,怎么獲取到的沒有了后面的小數0.375呢?計算機在處理浮點數會有精度損失。我們可以單獨做一個小測試:

1 <div id="box" style="position:absolute;left:30.2px;width:200px;height:300px;background:red;"></div>
2     <script>
3         var oBox = document.querySelector( '#box' );
4         alert( oBox.offsetLeft );
5     </script>

你會發現這段代碼獲取到左偏移是30px而不是行間樣式中寫的30.2px。因為在獲取當前位置的時候,會舍去小數,所以速度永遠停在0.375px, 位置也是永遠停在497,所以,為了到達目標,我們就得把速度變成1,對速度向上取整( Math.ceil ),我們就能把速度變成1,div也能到達500

 1 oBtn.onclick = function(){
 2     timer = setInterval( function(){
 3         speed = ( 500 - oBox.offsetLeft ) / 8;
 4         if( speed > 0 ) {
 5             speed = Math.ceil( speed );
 6         }
 7         console.log( speed, oBox.offsetLeft );
 8         oBox.style.left = oBox.offsetLeft + speed + 'px';
 9     }, 30 );
10 }

第二個問題,如果div的位置是在900,也就是說從900運動到500,有沒有這樣的需求呢? 肯定有啊,輪播圖,從右到左就是這樣的啊。

 1     <style>
 2         #box{
 3             width: 200px;
 4             height: 200px;
 5             background:red;
 6             position: absolute;
 7             left: 900px;
 8         }
 9     </style>
10     <script>// <![CDATA[
11         window.onload = function(){
12             var oBtn = document.querySelector( "input" ),
13                 oBox = document.querySelector( '#box' ),
14                 speed = 0, timer = null;
15             oBtn.onclick = function(){
16                 timer = setInterval( function(){
17                     speed = ( 500 - oBox.offsetLeft ) / 8;
18                     if( speed > 0 ) {
19                         speed = Math.ceil( speed );
20                     }
21                     oBox.style.left = oBox.offsetLeft + speed + 'px';
22                 }, 30 );
23             }
24         }
25     // ]]></script>
26 </head>
27 <body>
28     <input type="button" value="動起來">
29     <div id="box"></div>
30 </body>

 

 

 
 
最后目標停在503.5px,速度這個時候是負值,最后速度停在-0.5,對於反方向的速度,我們就要把它變成-1,才能到達目標,所以用向下取整(Math.floor)
 1 oBtn.onclick = function(){
 2     timer = setInterval( function(){
 3         speed = ( 500 - oBox.offsetLeft ) / 8;
 4         if( speed > 0 ) {
 5             speed = Math.ceil( speed );
 6         }else {
 7             speed = Math.floor( speed );
 8         }
 9         console.log( speed, oBox.offsetLeft );
10         oBox.style.left = oBox.offsetLeft + speed + 'px';
11     }, 30 );
12 }

然后我們把這個緩沖運動整合到勻速運動框架,就變成:

 1 function css(obj, attr, value) {
 2     if (arguments.length == 3) {
 3         obj.style[attr] = value;
 4     } else {
 5         if (obj.currentStyle) {
 6             return obj.currentStyle[attr];
 7         } else {
 8             return getComputedStyle(obj, false)[attr];
 9         }
10     }
11 }
12 
13 function animate(obj, attr, fn) {
14     clearInterval(obj.timer);
15     var cur = 0;
16     var target = 0;
17     var speed = 0;
18     obj.timer = setInterval(function () {
19         var bFlag = true;
20         for (var key in attr) {
21             if (key == 'opacity ') {
22                 cur = css(obj, 'opacity') * 100;
23             } else {
24                 cur = parseInt(css(obj, key));
25             }
26             target = attr[key];
27             speed = ( target - cur ) / 8;
28             speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
29             if (cur != target) {
30                 bFlag = false;
31                 if (key == 'opacity') {
32                     obj.style.opacity = ( cur + speed ) / 100;
33                     obj.style.filter = "alpha(opacity:" + ( cur + speed ) + ")";
34                 } else {
35                     obj.style[key] = cur + speed + "px";
36                 }
37             }
38         }
39         if (bFlag) {
40             clearInterval(obj.timer);
41             fn && fn.call(obj);
42         }
43     }, 30 );
44 }

有了這勻速運動框架,我們就來做幻燈片:

上下幻燈片的html樣式文件:

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>slide - by ghostwu</title>
 6     <link rel="stylesheet" href="css/slide3.css">
 7     <script src="js/animate.js"></script>
 8     <script src="js/slide.js"></script>
 9 </head>
10 <body>
11 <div id="slide">
12     <div id="slide-img">
13         <div id="img-container">
14             <img src="./img/1.jpg" alt="" style="opacity:1;">
15             <img src="./img/2.jpg" alt="">
16             <img src="./img/3.jpg" alt="">
17             <img src="./img/4.jpg" alt="">
18             <img src="./img/5.jpg" alt="">
19         </div>
20     </div>
21     <div id="slide-nums">
22         <ul>
23             <li class="active"></li>
24             <li></li>
25             <li></li>
26             <li></li>
27             <li></li>
28         </ul>
29     </div>
30 </div>
31 </body>
32 </html>
View Code

slide3.css文件:

 1 * {
 2     margin: 0;
 3     padding: 0;
 4 }
 5 li {
 6     list-style-type: none;
 7 }
 8 #slide {
 9     width: 800px;
10     height: 450px;
11     position: relative;
12     margin:20px auto;
13 }
14 #slide-img {
15     position: relative;
16     width: 800px;
17     height: 450px;
18     overflow: hidden;
19 }
20 #img-container {
21     position: absolute;
22     left: 0px;
23     top: 0px;
24     height: 2250px;
25     /*font-size:0px;*/
26 }
27 #img-container img {
28     display: block;
29     float: left;
30 }
31 #slide-nums {
32     position: absolute;
33     right:10px;
34     bottom:10px;
35 }
36 #slide-nums li {
37     float: left;
38     margin:0px 10px;
39     background: white;
40     width: 20px;
41     height: 20px;
42     text-align: center;
43     line-height: 20px;
44     border-radius:10px;
45     text-indent:-999px;
46     opacity:0.6;
47     filter:alpha(opacity:60);
48     cursor:pointer;
49 }
50 #slide-nums li.active {
51     background: red;
52 }
View Code

animate.js文件:

 1 function css(obj, attr, value) {
 2     if (arguments.length == 3) {
 3         obj.style[attr] = value;
 4     } else {
 5         if (obj.currentStyle) {
 6             return obj.currentStyle[attr];
 7         } else {
 8             return getComputedStyle(obj, false)[attr];
 9         }
10     }
11 }
12 
13 function animate(obj, attr, fn) {
14     clearInterval(obj.timer);
15     var cur = 0;
16     var target = 0;
17     var speed = 0;
18     obj.timer = setInterval(function () {
19         var bFlag = true;
20         for (var key in attr) {
21             if (key == 'opacity ') {
22                 cur = css(obj, 'opacity') * 100;
23             } else {
24                 cur = parseInt(css(obj, key));
25             }
26             target = attr[key];
27             speed = ( target - cur ) / 8;
28             speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
29             if (cur != target) {
30                 bFlag = false;
31                 if (key == 'opacity') {
32                     obj.style.opacity = ( cur + speed ) / 100;
33                     obj.style.filter = "alpha(opacity:" + ( cur + speed ) + ")";
34                 } else {
35                     obj.style[key] = cur + speed + "px";
36                 }
37             }
38         }
39         if (bFlag) {
40             clearInterval(obj.timer);
41             fn && fn.call(obj);
42         }
43     }, 30 );
44 }
View Code

slide.js文件:

 1 window.onload = function () {
 2     function Slide() {
 3         this.oImgContainer = document.getElementById("img-container");
 4         this.aLi = document.getElementsByTagName("li");
 5         this.index = 0;
 6     }
 7 
 8     Slide.prototype.bind = function () {
 9         var that = this;
10         for (var i = 0; i < this.aLi.length; i++) {
11             this.aLi[i].index = i;
12             this.aLi[i].onmouseover = function () {
13                 that.moveTop( this.index );
14             }
15         }
16     }
17 
18     Slide.prototype.moveTop = function (i) {
19         this.index = i;
20         for( var j = 0; j < this.aLi.length; j++ ){
21            this.aLi[j].className = '';
22         }
23         this.aLi[this.index].className = 'active';
24         animate( this.oImgContainer, {
25             "top" : -this.index * 450,
26             "left" : 0
27         });
28     }
29     
30     var oSlide = new Slide();
31     oSlide.bind();
32 
33 }
View Code
 
左右幻燈片只需要改下樣式即可
樣式文件:
 1 * {
 2     margin: 0;
 3     padding: 0;
 4 }
 5 li {
 6     list-style-type: none;
 7 }
 8 #slide {
 9     width: 800px;
10     height: 450px;
11     position: relative;
12     margin:20px auto;
13 }
14 #slide-img {
15     position: relative;
16     width: 800px;
17     height: 450px;
18     overflow: hidden;
19 }
20 #img-container {
21     position: absolute;
22     left: 0px;
23     top: 0px;
24     width: 4000px;
25 }
26 #img-container img {
27     display: block;
28     float: left;
29 }
30 #slide-nums {
31     position: absolute;
32     right:10px;
33     bottom:10px;
34 }
35 #slide-nums li {
36     float: left;
37     margin:0px 10px;
38     background: white;
39     width: 20px;
40     height: 20px;
41     text-align: center;
42     line-height: 20px;
43     border-radius:10px;
44     text-indent:-999px;
45     opacity:0.6;
46     filter:alpha(opacity:60);
47     cursor:pointer;
48 }
49 #slide-nums li.active {
50     background: red;
51 }
View Code

js調用文件:

 1 window.onload = function () {
 2     function Slide() {
 3         this.oImgContainer = document.getElementById("img-container");
 4         this.aLi = document.getElementsByTagName("li");
 5         this.index = 0;
 6     }
 7 
 8     Slide.prototype.bind = function () {
 9         var that = this;
10         for (var i = 0; i < this.aLi.length; i++) {
11             this.aLi[i].index = i;
12             this.aLi[i].onmouseover = function () {
13                 that.moveLeft( this.index );
14             }
15         }
16     }
17 
18     Slide.prototype.moveLeft = function (i) {
19         this.index = i;
20         for( var j = 0; j < this.aLi.length; j++ ){
21            this.aLi[j].className = '';
22         }
23         this.aLi[this.index].className = 'active';
24         animate( this.oImgContainer, {
25             "left" : -this.index * 800
26         });
27     }
28     
29     var oSlide = new Slide();
30     oSlide.bind();
31 
32 }
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM