banner 大图滚动

2,544 阅读8分钟
原文链接: zhuanlan.zhihu.com
小弟又出来献丑了,今天写一个大图滚动(应常用在banner中)分享给大家
闲话不多说,先看一下效果 大图滚动,看我来封装你

简单说一下效果:

第一个效果是自己写的结构,然后原生js实现

后二个效果是用对象new出来的,如果你也缺一个对象,来new一个吧

废话不多说,开始敲代码吧

首先创建大图滚动的结构
    • 1
    • 2
    • 3
    • 4
    • 5

    注释都详细解释清楚了,就不多说了,不过还是要多说一句,我的这个是固定结构,用过框架的都知道,写代码要按钮框架的要求来,包括类名,我这里也是一样的呦,哈哈就是这么霸道!(这里主要是方便对象的封装,要谅解呦)

    那么接下来,大家自己写吧!

    开个玩笑,下面继续样式
    
    
    		*{
    			margin: 0px;
    			padding: 0px;
    			border: 0px;
    		}
    
    		.lyc-container{
    			position: relative;
    			overflow: hidden;
    			 width: 1000px; 
    			margin: 100px auto;
    		}
    
    		.lyc-out{
    			position: relative;
    			 width: 1000px;
    			height: 300px; 
    			margin: 0px auto;
    			overflow: hidden;
    		}
    
    		.lyc-inner{
    			 width: 6000px;
    			height: 300px; 
    			overflow: hidden;
    		}
    		.lyc-inner li{
    			float: left;
    			list-style: none;
    		}
    
    		.lyc-inner img{
    			float: left;
    			width: 1000px;
    			height: 300px;
    		}
    
    		.lyc-imgs_indexs{
    			position: absolute;
    			bottom: 20px;
    			right: 20px;
    		}
    
    		.lyc-imgs_indexs li{
    			float: left;
    			list-style: none;
    			width: 30px;
    			height: 30px;
    			margin-left: 10px;
    			color: white;
    			font-size: 20px;
    			text-align: center;
    			line-height: 30px;
    			background-color: #c8c8c8;
    			border-radius: 100%;
    			cursor: pointer;
    		}
    
    		.lyc-imgs_indexs li:hover{
    			background-color: orange;
    		}
    
    		.lyc-imgs_indexs .lyc-current{
    			background-color: orange;
    		}
    
    		.lyc-left{
    			position: absolute;
    			left: 20px;
    			top: 50%;
    			width: 25px;
    			height: 24px;
    			margin-top: -12px;
    			background: url(img/left.png) no-repeat;
    			cursor: pointer;
    			z-index: 10;
    		}
    
    		.lyc-right{
    			position: absolute;
    			right: 20px;
    			top: 50%;
    			width: 25px;
    			height: 24px;
    			margin-top: -12px;
    			background: url(img/right.png) no-repeat;
    			cursor: pointer;
    			z-index: 10;
    		}
    	
    
    样式中能虽然定义了很多宽高,其实这些都会被覆盖的,这里只是作为默认样式,因为总不能一种风格贯穿所有界面吧,你们不腻,我都烦死了,待会在对象实例化中会看到具体参数配置,那就跳过去了,跳过去了。

    获取页面元素

    这是基本的js DOM操作啦,不详细讲啦
    var con=document.querySelector('.lyc-container');
    var out=document.querySelector(".lyc-out");
    var imgs=document.querySelector(".lyc-inner").getElementsByTagName('img');
    var imgs_indexs=document.querySelector(".lyc-imgs_indexs").getElementsByTagName("li");
    var left=document.querySelector(".lyc-left");
    var right=document.querySelector(".lyc-right");
    
    图片开始的下标
    定义两个计时器
    var timer1=null;//控制一张图片滚动的步数
    var timer2=null;//控制自动滚动
    

    好了,一切就绪,动起来!

    动起来吧!

    想让一张图片动起来
    function move(){
    	clearInterval(timer1);
    	var step=0;
    	var maxstep=30;//这里就是一张图片分为30小步来滚动
    	var startpos=out.scrollLeft;//每一次滚动前,out容器所在的位置
    	var endpos=imgs[0].offsetWidth*x;//out容器应该滚动到的地方
    	var every=(endpos-startpos)/maxstep;//out容器每一步滚动的距离
    
    	timer1=setInterval(function(){
    		step++;
    		if(step>=maxstep){//当滚动到最大步数时(这里是30步),也就是一张图片滚动结束时,清楚计时器
    		clearInterval(timer1);
    			step=0;
    		}
    		startpos+=every;
    		out.scrollLeft=startpos;
    	},15);//每一小步间隔时间15ms
    }
    

    怎么动呢,我们把一样图片的滚动分为30步,当然你也可以20步,10步,步数越少,滚动效果越不明显,然后让out的scrollLeft增加就行了,这样一张图片的滚动的就完成了。

    然后呢?当然是自己动

    上来,自己动!

    function automove(){
    	clearInterval(timer2);
    	timer2=setInterval(function(){
    		x++;
    		if(x>=imgs.length){
    			x=1;
    			out.scrollLeft=0;
    		}
    		move();
    		current();
    	},2000);//每一张图片滚动间隔2000ms,这里要注意,间隔一定要大于每一小步间隔时间乘以一张图片要滚动的步数,也就是2000>(15*30);
    }
    
    window.onload=function(){
    	out.scrollLeft=imgs[0].offsetWidth;
    	automove();
    };
    

    滚动的原理就是让srcollLeft增加而已,没有想象中的那么深奥,清理计时器的主要原因就是防止计时器的叠加,这就像**要戴套一样,安全,每一次都要请计时器,这样即使**多了,也是安全滴!

    循环滚动的原理
    大家有没有注意到滚动结构,第一张图片和最后一样一样的,这样当滚动到最后一张的时候,突然让out回到头部,这是瞬间回去的,我们肉眼凡胎是观察不到的,如果你就想看就像看,那这么办呢,告诉你一个办法 :在样式中把.lyc-out的overflow:hidden改为overflow-x:scroll;这样是不是就一目了然了呢!

    值得注意的是:我们的第二张图片对应下标一,也就是说我们默认为第二张图片是展示的第一页,哈哈,就是这么任性

    好,接着控制上一页下一页切换

    让上代码,再分析

    right.onclick=function(e){//点击向右按钮,向右滚动一张
    	var e=e||window.event;
    	clearInterval(timer1);
    	clearInterval(timer2);
    		x++;
    	if(x>=imgs.length){
    		x=1;
    		out.scrollLeft=0;
    	}
    	move();
    	current();
    	automove();
    }
    
    left.onclick=function(){//点击向左按钮,向左滚动一张
    	clearInterval(timer1);
    	clearInterval(timer2);
    	x--;
    	if(x<0){
    		x=imgs.length-2;
    		out.scrollLeft=(imgs.length-1)*imgs[0].offsetWidth;
    	}
    	move();
    	current();
    	automove();
    }
    

    看一个就行,左切,右切原理是一样的,只要使x增加和改变就行了,那其余的一大堆事干嘛的,当然是判断边界的,滚到头了,就让它从头滚

    接着页码切换
    for(var i=0;i

    其实和切换一样,这里只是把x的值设为你要点击的下标,大家可记得数组是从下标0开始的,而我们的图片默认是从第二张开始的,我们下标是1的时候,其实是第二张图片,也就是i=1对应着x=2,因此我们可以总结出i和x的关系,那就是私生子的关系,哦不,x=i+1,哈哈!

    下标的反应
    function current(){//标示出来当前的页
    	for(var i=0;i

    当我们点击下标的时候,是当前的下标改变颜色,不然我们在**的时候,不是总说女人的**才是最好的壮阳药,我又污le........

    总结

    这就是我们的大图滚动,不过这可还没完呢

    下面才是重点

    封装

    每次写个大图滚动都要写这么多代码,累不累呀,俗话说的好,只有累死的牛,没有耕坏的地,虽然我们很强,但还是要歇歇的,不然身体早晚要被掏空,身体被掏空用什么药来着。。。。扯远了,快回来。。。

    当我们想要一个大图滚动的时候这样写是不是很方便:

    然后就可以啦!

    我了个大X,前面写那么多都白费了,嗯嗯,是的,都可以删了

    好戏开始
    function Scroll(obj){
    	this.num = obj.num||5;//滚动的页数
    	this.width = obj.width||1000;//每一页的宽度
    	this.height = obj.height||300;//每一页的高度
    	this.src = obj.src;//图片来源
    	this.n = 1;//当前页
    	this.timer1 = null;//滚动一页的计时器
    	this.timer2 = null;//自动滚动的计时器
    	this.container = null;//滚动结构
    	this.out = null;//滚动容器
    	this.inner = null;//包裹容器
    	this.left = null;//向左滚动按钮
    	this.right = null;//向右滚动按钮
    	this.imgs_indexs = null;//图片序号
    	this.direction = obj.direction||false;//控制方向的箭头
    	this.index = obj.index||false;//滚动页的下标
    		     
    }
    

    我们先写出一个大图滚动对象的一些基本结构,都有注释,不解释。

    这一种方法,我们把所有结构都创建出来
    Scroll.prototype.init = function(){
    			//创建结构
    		     this.container = document.createElement("div");
    		     this.container.classList.add("lyc-container");
    		     this.container.style.width = this.width+"px";
    		     this.container.style.height = this.height+"px";
    		     this.out = document.createElement("div");
    		     this.out.classList.add("lyc-out");
    		     this.out.style.width = this.width+"px";
    		     this.out.style.height = this.height+"px";
    		     this.inner = document.createElement("ul");
    		     this.inner.classList.add("lyc-inner");
    		     this.inner.style.height = this.height+"px";
    		     this.inner.style.width=this.width*(this.num+1)+"px";
    
    		     //判断是否创建控制键
    		     if(this.direction){
    			     this.left = document.createElement("div");
    			     this.left.classList.add("lyc-left");
    			     this.right = document.createElement("div");
    			     this.right.classList.add("lyc-right");
    			     this.container.appendChild(this.left);
    			     this.container.appendChild(this.right);
    		     }
    
    		     //创建滚动页
    		     for(var i=0;i

    结构创建出来了,就是一些方法了,滚动,点击,切换等等,基本和刚才的一样,只是这里的变量全是这个对象的属性;再者需要注意的是this的保存,这里不详细讲,后续再加喽

    滚动
    Scroll.prototype.move = function(n){
    	var self = this;
    	var step = 0;
    	var maxstep = 20;
    	var pos = self.out.scrollLeft;
    	var end = this.width*n;
    	var every = (end-pos)/maxstep;
    
    	clearInterval(self.timer1);
    	self.timer1 = setInterval(function(){
    		 step++;
    		 if(step>=maxstep){
    		      clearInterval(self.timer1);
    		      self.out.scrollLeft=end;
    		      step=0;
    		  }
    		 pos+=every;
    		 self.out.scrollLeft=pos;
    	},10);
    }
    
    自动滚
    Scroll.prototype.automove = function(){
    	var self = this;
    	clearInterval(self.timer2);
    	self.timer2=setInterval(function(){
    		self.n++;
    		if(self.n>self.num){
    		     self.n=1;
    		     self.out.scrollLeft=0;
    		}
    		self.move(self.n);
    		self.current();
    	},2000);
    	self.arrow();
    	self.tap();
    }
    
    上下切换
    Scroll.prototype.arrow = function(){
    	var self = this;
    	if(!self.left){
    		return;
    	}
    	self.left.onclick=function(){
    		clearInterval(self.timer1);
    		clearInterval(self.timer2);
    		self.n--;
    		if(self.n<0){
    			self.n=self.num-1;
    			self.out.scrollLeft = self.width*self.num;
    		}
    		self.move(self.n);
    		self.current();
    		self.automove();
    	}
    	self.right.onclick=function(){
    		clearInterval(self.timer1);
    		clearInterval(self.timer2);
    		self.n++;
    		if(self.n>self.num){
    			self.n=1;
    			self.out.scrollLeft = 0;
    	        }
    	        self.move(self.n);
    	        self.current();
    	        self.automove();
    	}
    }
    

    下标切换

    Scroll.prototype.tap = function(){
    	var self = this;
    	if(!self.imgs_indexs){
    		return;
    	}
    	var imgs_index = self.imgs_indexs.getElementsByTagName("li");
    	for(var i=0;i

    最后来点反应

    Scroll.prototype.current = function(){
    	var self = this;
    	if(!self.imgs_indexs){
    		return;
    	}
    	var imgs_index = self.imgs_indexs.getElementsByTagName("li");
    	for(var i=0;i

    基本搞定

    new一个对象出来玩玩

    //创建第一个对象
    var scroll1 = new Scroll({
    	num:4,
    	width:1000,
    	 height:500,
    	src:["img/baihuzi2.jpg","img/nami1.jpg","img/wusuopu3.jpg","img/fulanqi3.jpg","img/shanzhi1.jpg"]
    });
    scroll1.init();
    
    //创建第二个对象
    var scroll2 = new Scroll({
            num:5,
    	width:600,
    	direction:true,
    	index:true,
    	src:["img/zuoluo1.jpg","img/zuoluo2.jpg","img/zuoluo3.jpg","img/luobin4.jpg","img/luobin1.jpg","img/luobin2.jpg"]
    });
    scroll2.init();
    

    一个岂能够,创建了两个,大家对比一下,第二个比第一个多了两个参数,direction属性呢是控制左右切换是否被创建出来,index属性是控制下标时候被创建出来,相应的,如果对应的结构没有被创建出来,那么相应的事件相应就不该存在,否则会报错,因此在封装的时候,我们进行了一个判断

    大家发现了没,我们并没有创建结构,而是对象自己new出来的,好处是省事,缺点的就是结构太局限了,我们这里只能调节宽高和图片来源,并不能往里面添加新的结构,下面我们看看第二种分装方法。

    依据固定结构封装

    我们还用上面写的结构,因为我们有结构的,因此不需要创建了,只需要获取DOM就可以了;

    对象结构(和第一种没什么区别)
    function Scroll1(obj){
    	 this.num = null;//滚动的页数
    	 this.width = 1000;//每一页的宽度
    	 this.height = 300;//每一页的高度
    	 this.n = 1;//当前页
    	 this.timer1 = null;//滚动一页的计时器
    	 this.timer2 = null;//自动滚动的计时器
    	 this.container = null;//滚动结构
    	 this.out = null;//滚动容器
    	 this.inner = null;//包裹容器
    	 this.left = null;//向左滚动按钮
    	 this.right = null;//向右滚动按钮
    	 this.imgs_indexs = null;//图片序号		     
    }
    

    获取DOM

    Scroll1.prototype.init = function(obj){
    	//初始化容器
    	this.container = document.querySelector(obj);
    	this.out = this.container.querySelector(".lyc-out");
    	this.inner = this.container.querySelector(".lyc-inner");
    	this.num = this.inner.querySelectorAll("li").length-1;
    	this.inner.style.height = this.height+"px";
    	this.inner.style.width=this.width*(this.num+1)+"px";
    	this.imgs_indexs = this.container.querySelector(".lyc-imgs_indexs");
    	this.left = this.container.querySelector(".lyc-left");
    	this.right = this.container.querySelector(".lyc-right");
    	this.out.scrollLeft = this.width;
    	//自动滚动开始
    	this.automove();
    }
    

    对象的方法和第一种一样,这里就不贴代码了

    这里的结构呢,就很放松了,你可以在li里面添加想要的元素,是不是方便多了,下面来个实例;

    //初始化页面存在的结构
    var scroll = new Scroll1();
    scroll.init(".lyc-container");//.lyc-container大图滚动初始化的dom元素
    

    敲了这么多代码,比**都累,感觉身体被掏空,希望对你们有帮助吧!

    唠叨一句

    js远比我们想象的nb,有一句话说的好,凡是可以用js写的,以后都会用js写,程序猿,加油吧!