• [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              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;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              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
  • 相关阅读:
    [转]PHP如何关闭notice级别的错误提示
    [原]php远程odbc连接sqlsvr数据库,自定义端口,命名实例的连接方式
    [原] wmic: Invalid XSL format (or) file name错误解决方法
    [转]PHP Session的一个警告
    [转]权限问题导致Nginx 403 Forbidden错误的解决方法
    [转]require(),include(),require_once()和include_once()区别
    [转]Mysql命令行常用操作
    php读取sql2000的image字段,被截断的问题
    一、基于hadoop的nginx访问日志分析---解析日志篇
    shell判断条件整理
  • 原文地址:https://www.cnblogs.com/ghostwu/p/7677105.html
Copyright © 2020-2023  润新知