基于原生javascript的图片轮播domo

现在很多javascript的插件都可以实现图片轮播的功能,这篇文章,主要是通过这个domo来解析javascript图片轮播的原理。

老规矩,先上代码。至于代码中的图片,随便找三张即可,最核心的还是理解其思想。

html:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title>滚动图</title>
		<link rel="stylesheet" type="text/css" href="css/scroll.css"/>
	</head>
	<body>
		<div id="wrapper">
			<div id="box">
				<img src="img/banner0.png"/>
				<img src="img/banner1.png"/>
				<img src="img/banner2.png"/>
			</div>
			<div id="pointer">
				<span class="active"></span>
				<span></span>
				<span></span>
			</div>
		</div>
		<script src="js/scroll.js" type="text/javascript" charset="utf-8"></script>
	</body>
</html>


css:

*{
	margin: 0;
	padding: 0;
}
#wrapper{
	position: relative;
	width: 1200px;
	margin: 50px auto;
	overflow: hidden;
}
#pointer{
	clear: both;
	position: absolute;
	right: 500px;
	bottom: 15px;
	width: 180px;
	height: 2px;
}
#pointer span{
	display: block;
	box-sizing: border-box;
	float: left;
	width: 50px;
	height: 1.5px;
	margin-right: 10px;
	border-radius: .5px;
	background: #fff;
	opacity: .5;
	-webkit-opacity: .5;
	-moz-opacity: .5;
	filter:alpha(opacity=50);
}
#pointer .active{
	opacity: .8;
	-webkit-opacity: .8;
	-moz-opacity: .8;
	filter:alpha(opacity=80);
}
#box{
	position: relative;
	width: 3600px;
	clear: both;
}
img{
	display: block;
	float: left;
	width: 1200px;
	height: 337px;
}


javascript:

window.onload = function(){
	//获取装图片的盒子
	var box = document.getElementById('box');
	//获取装页码的盒子
	var pointer = document.getElementById('pointer');
	//获取盒子中的所有图片
	var imglist = box.getElementsByTagName('img')
	//获取盒子中的所有页码
	var pointerList = pointer.getElementsByTagName('span');
	//图片的宽度,正负用于左右的循环
	var n = -1200;
	//增加一倍的图片用于循环
	box.innerHTML = box.innerHTML+box.innerHTML;
	//设置盒子的宽
	box.style.width = imglist[0].offsetWidth*imglist.length+"px";
	var timer = null;
	timer = setInterval(function(){
		scroll(box,n,pointerList);
	},3000);
	box.onmouseover = function(){
		clearInterval(timer);
	}
	pointer.onmouseover = function(){
		clearInterval(timer);
	}
	box.onmouseout = function(){
		timer = setInterval(function (){
//			console.log(new Date());
			scroll(box,n,pointerList);
		},3000);
	}
	//设置页码的点击事件
	for(var i=0;i<pointerList.length;i++){
		pointerList[i].index=i;//设置一个参数,用下面调用某个页码
		//如果不设置参数,在调用页码的时候会直接调用最后一个,因为我们使用了循环
		pointerList[i].οnclick=function (){
			for(var j=0;j<pointerList.length;j++){
				pointerList[j].className='';//清空激活的class
			}
			move(box,n*(this.index));//移动图片
			this.className='active';//激活点击的页码
		}
	}
	
}
/**
 * 循环滚动函数
 * @param {Object} box
 * @param {Object} n
 */
function scroll(box,n,page){
	//判断是否到达临界点,即box的中间部分
	if(box.offsetLeft<=-box.offsetWidth/2){
		box.style.left = "0px";//重新从头开始
		console.log('0');
	}
	if(box.offsetLeft%n!=0){
		//因为在我们切换浏览器标签页或者切换去其他软件界面的时候,
		//会影响到setInterval,有时候setInterval会增加好几秒,在这里我们必须加一个判断
		//只有当它走完了一个整个的图片宽度时,我们才进行下一次滚动。
	}
	else{
		pageScroll(box,n,page);
		move(box,n+box.offsetLeft);
	}
}
/**
 * 滚动页码函数
 * @param {Object} box
 * @param {Object} n
 * @param {Object} page
 */
function pageScroll(box,n,page){
	//直接通过图片盒子的定位判断页码值,但是此时的页码值是滚动之前的,所以后面的值要+1使用
	var index = Math.abs(box.offsetLeft/n);
	console.log(index);
	for(var i=0;i<page.length;i++){
		page[i].className='';
	}
	//判断是不是最后一页,是最后一页的话+1要变成0;
	if(index<page.length-1){
		page[index+1].className='active';
	}
	else{
		page[0].className='active';
	}
}

/**
 * 变速移动
 * @param {Object} ele
 * @param {Object} target
 */
function move(ele,target){ 
	clearInterval(ele.timer);
	console.log(new Date());
    ele.timer = setInterval(function () {
	    var step = (target-ele.offsetLeft)/10;
	    step = step>0?Math.ceil(step):Math.floor(step);
	    if(target==ele.offsetLeft){
	        console.log(new Date());
	        clearInterval(ele.timer);
	    }
	    else{
	    	ele.style.left = ele.offsetLeft + step + "px";
	    }
	},30);
}


html和css部分依旧比较简单,直接跳过。javascript部分的代码注释写的也比较详细,下面主要讲解逻辑部分。

图片滚动的原理是利用setInterval函数进行背景图片的不断循环。为了避免图片循环的过程中出现间断,首先是在javascript中进行图片的复制(增加一倍),然后当到达临界点时,瞬间将图片移动到初始的位置,然后开始下一轮循环。

在这个domo中,主要包含四个函数:

1、外层控制间隔时间的函数。这个比较容易理解,通过setInterval函数每隔几秒循环执行一次图片滚动的函数。

2、中间层滚动函数。判断图片盒子是否到达临界点,判断当前状态是否符合进入下一次滚动(这个条件主要是为了防止切换界面对setInterval函数的影响,具体原因在最后)。

3、中间层页码滚动函数。基本没有难点,主要是理解页码为什么+1即可。

4、图片滚动函数。这个在之前写过的一篇文章有详细讲解,不再赘述。 javascript匀速动画和缓冲动画


最后,一点关于setInterval底层机制的扩展。

我们内层函数的执行事件正常情况下为1-2s(测试过),而外层的循环需要3s才进行一次,正常的情况是没有问题的。但是,当你切换界面的时候,浏览器就会对setInterval函数产生影响,此时执行事件的事件就会超过3面,在没移动结束的情况下开启另一个定时器进行下一次图片滚动,所以就会发生错乱。

javascript是单线程的,当你使用setInterval函数的时候并不是真正暂停,而是先挂起这个事件,继续执行下面的事件,而当这个事件要执行时,如果浏览器当前没有任务,那么它会立马执行,但是如果浏览器有任务,那么就会有一定的延迟,这也是为什么切换界面会对setInterval函数的时间产生影响。

(关于setInterval函数的理解如有错误,欢迎指正!如果大家想要深入理解,也可以去一些大神的博客看一下setInterval函数的文章)




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值