zoukankan      html  css  js  c++  java
  • 简单的图片无缝滚动效果

    经常在做网页中遇到需要展示一组或几组图片的情况,于是图片的无缝滚动效果成为比较常见的效果之一。往往我们时间有限,所以常求助于jQuery的图片滚动插件。

    前段时间,我觉得仅仅需要一个这样的特效而把整个jQuery库引入项目中实在太耗费性能,于是自己动手做了一个,下面是简陋的雏形:

    原理比较简单,就是在页面初始化时将首尾的图片各复制一个分别放至结尾和开头,如下图所示:

    1、2、3代表3组滚动的图片,1号结点为起始位置,当点击右按钮时,图片从1号结点向右滚动,直到clone3结点,结束后立即将位置从clone3定位到3号结点;再点击向右按钮时,就从3号结点滚动到2号结点,

    这样看起来就实现了无缝滚动,点击左按钮与点击右按钮的原理相同。

    函数中主要包含两个方法:

      init方法——该方法做一些初始化操作,比如记录每组图片当前的位置,一共几组图片,克隆首尾结点等;

      animate方法——该方法执行点击了左或右按钮后的动画效果

    以下是init方法的一些代码:

     1        init:function(params) {
     2                 params = params || {};
     3                 //获取外层容器对象
     4                 this.target = params.id || $('b');
     5                 //是否自动滚动
     6                 this.autoScroll = params.autoScroll || false;
     7                 //用于保存间歇函数
     8                 this.t = null;
     9                 //将容器的属性保存至局部变量
    10                 var p = this.target.getBoundingClientRect();
    11                 //计算容器的宽度,IE没有width属性,故用后者代替
    12                 this.width = p.width || p.right - p.left;
    13                 //获取内层容器
    14                 this.box = getElementsByClass('c')[0];
    15                 //定义一个数组用于保存内层容器内的子节点,即共有几组滚动图片
    16                 var nodeArr = [];
    17                 for(var i = 0,len = this.box.childNodes.length; i < len; i++) {
    18                     /*
    19                      *由于可能取到的结点可能为文本,必须排除文本节点
    20                      *元素节点类型取值(nodeType)
    21                      *元素element    1
    22                      *属性attr    2
    23                      *文本text    3
    24                      *注释comments    8
    25                      *文档document    9
    26                      */
    27                     if(this.box.childNodes[i].nodeType == 1) {
    28                         //将符合的节点推入数组
    29                         nodeArr.push(this.box.childNodes[i]);
    30                     }
    31                 }
    32                 //将需要滚动图片的数量保存到一个变量
    33                 this.num = nodeArr.length;
    34                 //克隆首尾的节点
    35                 var first = nodeArr[0],
    36                     last = nodeArr[nodeArr.length - 1],
    37                     firstClone = first.cloneNode(true),
    38                     lastClone = last.cloneNode(true);
    39                 //将克隆的节点新增clone样式作为标识
    40                 firstClone.className = lastClone.className = 'd clone';
    41                 //分别将末节点和首节点的克隆添加到第一位和最后一位
    42                 this.box.insertBefore(lastClone,first);
    43                 this.box.appendChild(firstClone);
    44 
    45                 //获取左按钮和右按钮
    46                 this.parent = this.target.parentNode;
    47                 var prev = getElementsByClass('prev',this.parent,'a')[0],
    48                     next = getElementsByClass('next',this.parent,'a')[0];
    49 
    50                 //初始化位置
    51                 var w = this.width;//保存每组滚动图片(一组四张图片)的宽度
    52                 /*将开始位置设置为第一组滚动图片,在第一组滚动图片前有一个clone节点,left值为0
    53                 故第一组的滚动图片的位置为-this.width*/
    54                 this.box.style.left = -this.width + 'px';
    55 
    56                 //设置缓动函数的相关变量
    57                 this.b = -w;            //由于是从第一组图片开始的,所以初始位置为一组图片的宽度,方向为负(左为正方向)
    58                 this.c = -w;            //位移,即滚动一次经过的路程,方向为负(左为正方向),值和每组图片的宽度相等
    59                 this.d = 50;            //缓动的总时间
    60                 this.t = 0;             //当前经过的时间
    61 
    62                 //定义一个数组,用来保存每组图片的位置
    63                 this.initPos = [];
    64                 //每一组滚动图片对应一个索引,初始化时将索引至为1
    65                 this.index = 1;
    66                 //加上克隆的节点,一共有this.num + 2个节点
    67                 for(var j = 0,num = 0,l = this.num+2; j < l; j++) {
    68                     this.initPos.push(-w * num++);
    69                 }
    70 
    71                 //console.log(this.initPos);    //[0,-600,-1200,-1800,-2400]
    72 
    73                 //设置布尔值,判断动画是否完成
    74                 this.prevAllow = true;
    75                 this.nextAllow = true;
    76                 var self = this;
    77                 //添加左右按钮单击事件
    78                 addEvent(prev,'click',self.animate.bind(self,'left'));
    79                 addEvent(next,'click',self.animate.bind(self,'right'));
    80 
    81                 //如果开启自动滚动则每三秒滚动一次
    82                 this.autoScroll && (this.t = setInterval(function() {
    83                     self.animate('left');
    84                 },3000));
            },

    在该方法的最后注册了左右按钮的点击事件,调用的是animate方法:

     1        /*
     2              * 点击左右按钮时执行的操作
     3              * @param {string} left || right 传入的参数表示点击了哪边的按钮
     4              */
     5             animate:function(button) {
     6                 var self = this,
     7                     //获取滚动容器
     8                     box = this.box,
     9                     boxStyle = box.style;
    10 
    11                 switch(button) {
    12                     case 'left':
    13                         if(this.prevAllow) {
    14                             //防止在动画完成前连续点击按钮进行多次操作
    15                             this.prevAllow = false;
    16                             //将初始位置设置为当前的索引值
    17                             this.b = this.initPos[this.index];
    18                             //每点一次左按钮,索引加1,若超过索引最大值则返回0,表示滚动到头需要重新从第一组开始
    19                             this.index = (this.index > this.initPos.length - 1) ? 0 : this.index + 1;
    20                             //设置需要的位移,方向向左,负值
    21                             this.c = this.initPos[1];
    22                             //每点一次需要将当前时间重置为0以免受到上一次计时的影响
    23                             this.t = 0;
    24                             (function() {
    25                                 //使用缓动函数计算位移,直至动画完成
    26                                 boxStyle.left = easeOut(self.t,self.b,self.c,self.d) + 'px';
    27                                 if(self.t < self.d) {
    28                                     self.t++;
    29                                     setTimeout(arguments.callee,15);
    30                                 } else {//动画完成后解除连续点击按钮锁定
    31                                     self.prevAllow = true;
    32                                 }
    33                                 //假如向左滚动到最后一组图片(clone),则将其left设置为第一组图片
    34                                 if(parseInt(boxStyle.left) == self.initPos[self.initPos.length-1]) {
    35                                     boxStyle.left = self.initPos[1] + 'px';
    36                                     //同时重置索引
    37                                     self.index = 1;
    38                                 }
    39                             })();
    40                         }
    41                         break;
    42                     case 'right':   //点击向右按钮时
    43                         if(this.nextAllow) {
    44                             //防止在动画完成前连续点击按钮进行多次操作
    45                             this.nextAllow = false;
    46                             //将初始位置设为当前的索引值
    47                             this.b = this.initPos[this.index];
    48                             //更新索引
    49                             this.index = (this.index > 0) ? this.index - 1 : this.initPos.length - 1;
    50                             //设置需要的位移,方向向右,正值
    51                             this.c = -this.initPos[1];
    52                             //每点一次需要将当前时间重置为0以免受到上一次计时的影响
    53                             this.t = 0;
    54                             (function() {
    55                                 //使用缓动函数计算位移,直至动画完成
    56                                 boxStyle.left = easeOut(self.t,self.b,self.c,self.d) + 'px';
    57                                 if(self.t < self.d) {
    58                                     self.t++;
    59                                     setTimeout(arguments.callee,15);
    60                                 } else {//动画完成后解除连续点击按钮锁定
    61                                     self.nextAllow = true;
    62                                 }
    63                                 //假如向右滚动到第一组图片(clone节点),则将其left设置为最后一组图片
    64                                 if(parseInt(boxStyle.left) == self.initPos[0]) {
    65                                     boxStyle.left = self.initPos[self.initPos.length-2] + 'px';
    66                                     //同时将索引重置为当前组的索引
    67                                     self.index = self.initPos.length-2;
    68                                 }
    69                             })();
    70                         }
    71                         break;
    72                     default:
    73                         break;
    74                 }
    75             }
    76         };

    最后是构造函数:

    1 function Scroll() {
    2     return this.init.apply(this,arguments);
    3 }
    4 
    5 Scroll.prototype = {
    6     init:function(){/*code*/},
    7     animate:function(){/*code*/}
    8 }
    new Scroll();

    虽然没有jQuery插件中强大的功能,比如传入横向或竖直滚动的参数,设置是否无缝滚动等,但基本也算满足了项目的需要,同时代码体积缩小了不少。

    由于没有研究过jQuery插件实现这种效果的代码,效果是实现了,但代码和逻辑都不算好,还请高手不要鄙视,多多给予意见。

     源码:图片无缝滚动

    -------------------------------

    转载请注明出处。

  • 相关阅读:
    导入旧版本Android项目时的“Unable to resolve target ‘android
    eclipse打开文件目录
    ireport常见问题
    【技术贴】解决127.0.0.1和http://localhost均被拦截跳转到另一个网页
    【技术贴】SqlServer2008 R2 安装失败提示出现以下错误 服务 MSSQLSERVERO
    【技术贴】解决xp下Microsoft.SqlServer.Management.PSProvider.dll
    websphere性能设置和日常维护
    【技术贴】解决支付宝充值信用卡还款跳转到网上银行报错Error 404
    jQuery制作Facebook Timeline时间轴
    借助rownum中求Oracle表中前三名(三甲:状元榜眼探花)的方法(总计三种方法,以讲述rownum的使用为主)
  • 原文地址:https://www.cnblogs.com/undefined000/p/2696005.html
Copyright © 2011-2022 走看看