简单的图片无缝滚动效果

经常在做网页中遇到需要展示一组或几组图片的情况,于是图片的无缝滚动效果成为比较常见的效果之一。往往我们时间有限,所以常求助于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插件实现这种效果的代码,效果是实现了,但代码和逻辑都不算好,还请高手不要鄙视,多多给予意见。

 源码:图片无缝滚动

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

转载请注明出处。

原文地址:https://www.cnblogs.com/undefined000/p/2696005.html