原生js实现轮播图详解全

10 篇文章 0 订阅
一、原理

每次只显示一张图片,其余隐藏。通过计算偏移量利用定时器实现自动播放,或通过手动点击事件切换图片。

二、实现:
  • 给最外面的div容器固定的宽高,使内部的ul和li与div宽高相同(height:100%;width:100%),设置overflow:hidden,只显示一张图片
  • 为了实现无缝切换效果,利用两张辅助图填补最后一张图切换到第一张图时的空白。即复制最后一张图片放置在第一张图片前,同时复制第一张图片放置在最后一张图片的后面。
  • 让内部的ul强制不换行(white-space: nowrap; ),即所有的li排成一行,并且让ul往前平移自身的宽度(transform: translateX(-100%);),即默认显示实际图片的第一张图。
三、代码展示
  1. banner.html
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<link rel="stylesheet" type="text/css" href="css/reset.css"/>
		<link rel="stylesheet" type="text/css" href="css/public.css"/>
		<link rel="stylesheet" type="text/css" href="css/banner.css"/>
		<title></title>
	</head>
	<body>
		<div class="banner">
			<!-- 真正滑动的是ul -->
			<ul class="banner-slider">
				<!-- 在第一张之前多放一个最后一张,在最后一张多放一张第一张,目的是实现无缝轮播 -->
				<li><a href="#"><img src="images/banner-004.jpg" ></a></li>
				<li><a href="#"><img src="images/banner-001.jpg" ></a></li>
				<li><a href="#"><img src="images/banner-002.jpg" ></a></li>
				<li><a href="#"><img src="images/banner-003.jpg" ></a></li>
				<li><a href="#"><img src="images/banner-004.jpg" ></a></li>
				<li><a href="#"><img src="images/banner-001.jpg" ></a></li>
			</ul>
			<!-- 指示器 -->
			<ul class="banner-indicator">
				<li class="active"></li>
				<li></li>
				<li></li>
				<li></li>
			</ul>
			<!-- 两边的耳朵,左右箭头 -->
			<span class="banner-prev"></span>
			<span class="banner-next"></span>
		</div>
		
		<script src="js/banner.js" type="text/javascript" charset="utf-8"></script>
	</body>
</html>
  1. banner.css
/* 思路:
使ul和li设置的与div宽高相同,最外面的大div固定,里面的ul带着li跑。
 */
.banner {
	width: 1000px;
	height: 400px;
	margin: 100px auto;
	position: relative;
	overflow: hidden;
}
ul.banner-slider {
	/* transition: all 1s ease-out; 这里的过渡切换动画时间由js控制 */
	transition-property: all;
	transition-timing-function: ease-out;
	width: 100%;
	height: 100%;
	font-size: 0;
	white-space: nowrap; /* 强制不换行,使得所有的li排在一行 */
	transform: translateX(-100%); /* 由于第一张前多加了一张,所以需要ul往前平移一张图片的距离,默认显示实际的第一张 */
}
ul.banner-slider>li {
	display: inline-block;
	width: 100%;
	height: 100%;
}
ul.banner-slider>li>a {
	display: block;
	height: 100%;
}
ul.banner-slider>li>a>img {
	width: 100%;
	height: 100%;
} 

/* banner指示器 */
ul.banner-indicator {
	position: absolute;
	bottom: 25px;
	/* 先向左平移50%,再平移自身的一半,即实现居中显示 */
	left: 50%;
	transform: translateX(-50%);
}
ul.banner-indicator>li {
	float: left;
	width: 50px;
	height: 20px;
	background-color: rgba(0,0,0,0.5);
	border-radius: 4px;
	overflow: hidden; /* 由于四个角显示了圆角,所以需要将多余的部分隐藏掉 */
	margin: 0 10px;
}
/* 实现指示器切换的过渡动画 */
ul.banner-indicator>li::before {
	content: '';
	float: right;
	width: 0;
	height: 100%;
	background-color: coral;
	transition: all 1s ease-out; /* 与上面的动画过渡时间相同 */
}
ul.banner-indicator>li.active::before {
	width: 100%;
	float: left;
}

/* 左右两个耳朵 */
span.banner-prev,span.banner-next {
	width: 50px;
	height: 100px;
	position: absolute;
	top: 50%;
	transform: translateY(-50%);
	background-color: rgba(0,0,0,0.3);
	cursor: pointer;
}
span.banner-prev:hover,span.banner-next:hover {
	background-color: rgba(0,0,0,0.6);
}
span.banner-prev {
	left: 5%;
}
span.banner-next {
	right: 5%;
}
  1. banner.js
//全局变量
var index = 0; //记录当前哪一张是激活的,默认实际图片的第一张
var interval = 5000; //轮播图轮播的间隔时间(观看时间5s换下一张)
var timer = null;  //保存计时器对象
var count = 4;     //总共实际要轮播的图片数量
var lock = false;  //标识是否在执行动画,解决频繁点击下一张出现的bug,默认不执行动画,没有锁。

//自动播放、点击轮播图指示器、点击上一张下一张按钮的时候 三种情况都可调用该切换函数
//切换函数slide——核心函数
//将下一张编号的更新操作全部都放在了slide函数中,其它函数则不用考虑编号更改问题。
function slide(nextIndex) {
	//nextIndex(下一张编号):可取到 -1,0,1,2,3,4
	//index:0 1 2 3
	
	if(lock) return; //如果当前正在执行轮播动画,已经加锁,则直接返回
    lock = true;   //没加锁,接着开始执行轮播动画,需要加锁!
	//图片切换
	var slider = document.querySelector('ul.banner-slider');
	slider.style.transitionDuration = '1s';
	slider.style.marginLeft = -1 * nextIndex + '00%';
	
	//指示器切换
	var indicators = document.querySelectorAll('ul.banner-indicator>li');
	indicators[index].className = ''; //让当前激活的indicator不激活

	//更新index(三种情况通用)
	if(nextIndex === count) index = 0; //若下一张到了4,则立即回到第一张0
	else if(nextIndex === -1) index = count - 1;
	else index = nextIndex;
	
	indicators[index].className = 'active'; //让更新后的index激活
	
	//重置实现无缝效果
	setTimeout(function() {
		slider.style.transitionDuration = '0s'; //不设置动画,秒回到第一张,回到第一张后再执行上面的动画
		if(nextIndex === count) slider.style.marginLeft = '0%';
		if(nextIndex === -1) slider.style.marginLeft = -1 * (count - 1) +'00%';
		lock = false; //动画结束后,开锁!
	},1020);
}

//自动播放
function play() {
	//每隔指定时间滑动(切换)一次
    timer = setInterval(function() {
	     slide(index + 1);
},interval);
}

//鼠标滑过banner区域,暂停自动播放
document.querySelector('.banner').onmouseover = function() { clearInterval(timer);};
//鼠标滑出banner区域,恢复自动播放
document.querySelector('.banner').onmouseout = function() { play(); };

// 点击指示器切换轮播图
var indicators = document.querySelectorAll('ul.banner-indicator>li');
for(var i = 0; i < indicators.length; i++) {
	//将每一个li绑定一个属性num,用来藏每一个li的序号,则滑动时用这个序号标识滑到第几张即可
	indicators[i].num = i;
	indicators[i].onclick = function() {
        if(this.className === 'active') return;
		slide(this.num);
	};
}

//上一张 点击事件绑定(左箭头)
document.querySelector('span.banner-prev').onclick = function() {
	slide(index - 1); 
};

//下一张 点击事件绑定(右箭头)
document.querySelector('span.banner-next').onclick = function() {
	slide(index + 1);
};

//调用play开始首次自动播放
play();
四、总结

(1)容器的css布局。
(2)核心是切换函数,将编号的更新集中处理。每一次轮播通过偏移量(margin-left)实现。
(3)自动轮播,通过setInterval()方法实现定时器,执行切换函数
(4)鼠标控制轮播的暂停和继续。通过onmouseover为暂停(利用clearInterval() 清除计时器),onmouseout为继续。

五、效果展示

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值