jQuery实现轮播效果

个人博客上线欢迎来访 http://www.zihanzy.com

HTML结构

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        *{
            padding:0;
            margin:0;
            text-decoration: none;
        }
        body{
            /* padding:20px; */
        }
        #container{
            width:600px;
            height: 400px;
            overflow: hidden; /*图片超出部分隐藏*/
            position: relative;
            margin:0 auto;
        }
        #list{
            width:3000px; /* 5张图片的宽度 5*600 */
            height: 400px;
            position: absolute;
            z-index: 1;
        }
        #list img{
            float:left;
            width: 600px;
            height: 400px;
        }
        #dot{
            position:absolute;
            height: 10px;
            width: 100px;
            z-index: 2;
            bottom:20px;
            left:250px;
        }
        #dot .on{
            background:orangered
        }
        #dot span{
            cursor:pointer;
            float:left;
            width: 15px;
            height: 15px;
            border-radius: 50%;
            margin:0 auto;
            background-color: rgba(0,0,0,.7);
        }
        .arrow{
            cursor:pointer;
            display: none;
            line-height: 39px;
            text-align: center;
            font-size: 36px;
            font-weight: bold;
            width: 40px;
            height: 40px;
            position: absolute;
            z-index: 2;
            top:180px;
            background-color: rgba(0,0,0,0.3);
            color:#fff;

        }
        .arrow:hover{
            background-color: rgba(0,0,0,.7);
        }
        /* 鼠标移动到整个div区域时 */
        #container:hover .arrow{
            display: block;
        }
        #prev{
            left:20px;
        }
        #next{
            right: 20px;
        }
    </style>
</head>
<body>
    <div id="container">
        <div id="list">
            <img src="./images/1.jpg" alt="">
            <img src="./images/2.jpg" alt="">
            <img src="./images/3.jpg" alt="">
            <img src="./images/4.jpg" alt="">
            <img src="./images/5.jpg" alt="">
        </div>
        <div id="dot">
            <span index="1" class="on"></span>
            <span index="2" class=""></span>
            <span index="3" class=""></span>
            <span index="4" class=""></span>
            <span index="5" class=""></span>
        </div>
        <a href="javascript:;" id="prev" class="arrow"><</a>
        <a href="javascript:;" id="next" class="arrow">></a>
    </div>

需求分析

  1. 点击向右(左)的图标 平滑到下一页
  2. 无限循环切换,第一页的上一页为最后页,最后一页的下页是第一页
  3. 每隔3s自动滑动到下一页
  4. 当鼠标进入图片区域时,自动切换停止,当鼠标离开后自动切换开始
  5. 切换页面时,下面的圆点同步更新
  6. 点击圆点图标切换到对应的页

点击向右(左)的图标 平滑到下一页
要实现点击箭头向做向右移动我们需要

  1. 设置每次偏移量 PAGE_WIDTH
  2. 设置翻页持续的时间 TIME
  3. 设置单元移动的间隔时间 ITEM_TIME
  4. 求出单元移动的偏移量 itemOffset = offset(偏移量)/(TIME/ITEM_TIME)
  5. 计算出要移动到的目标位置
  6. 循环定时器进行平滑移动

代码实现

	$(function(){        
	var $container = $('#container')
	var $list = $('#list')
	var $dot = ('#dot span')
	var $prev = $('#prev')
	var $next = $('#next')
	var PAGE_WIDTH = 600 //偏移常量
	var TIME = 400 //翻页持续时间
	var ITEM_TIME = 20 //单元间隔时间

	//1.点击向右(左)的图标 平滑到下一页
	$next.click(function(){
			//平滑下一页
			nextPage(true)
	})
	$prev.click(function(){
			//平滑上一页
			nextPage(false)
	})

	/**
	 平滑翻页
		true:下一页
		false:上一页
	*/
	function nextPage(next){
		 var offset = 0
		 //计算offset 偏移量
		 var offset = next ? -PAGE_WIDTH : PAGE_WIDTH
		 //计算单元移动的偏移量 itemoffset
		 var itemOffset = offset/(TIME/ITEM_TIME)
		 //获取当前currentLeft
		 var currentLeft = $list.position().left 
		 //计算出目标处的left值
		 var targetLeft = currentLeft + offset
		 //循环定时器
		 var timer  = setInterval(() => {
				 //计算最新的current
				 currentLeft += itemOffset
				 //判断是否到底目标位置
				 if(currentLeft ===targetLeft){
						 //清除定时器
						 clearInterval(timer) 
				 }
				 $list.css('left',currentLeft)

		 }, ITEM_TIME);
	}
})

实现切换无缝滚动
为了实现无缝滚动的效果我们要在第一张图片前面添加最后一张图片,在最后一张图片后面添加第一张图片
当切换到克隆的(第一张/最后一张)图片时,跳转到真正的图片

修改css

 #list{
	width:4200px; /* 7张图片的宽度 7*600 */
	height: 400px;
	position: absolute;
	z-index: 1;
}

修改html结构

<div id="list" style="left:-600px">
	<img src="./images/5.jpg" alt="">
	<img src="./images/1.jpg" alt="">
	<img src="./images/2.jpg" alt="">
	<img src="./images/3.jpg" alt="">
	<img src="./images/4.jpg" alt="">
	<img src="./images/5.jpg" alt="">
	<img src="./images/1.jpg" alt="">
</div>

js部分

...
var ITEM_TIME = 20 //单元间隔时间
 //获取图片数量
var imgCount = $dot.length;
...
//定时器循环滚动
var timer = setInterval(() => {
	currentLeft+=itemOffset
	if(currentLeft === targetLeft){
			clearInterval(timer)
			//在滚动到最后一张图片的瞬间,跳转到第一张克隆的最后一张图片
			if(currentLeft === -(imgCount+1) * PAGE_WIDTH){
					currentLeft = -PAGE_WIDTH
			}else if(currentLeft === 0){
					//在滚动到第一张图片的瞬间(克隆的最后一张图片),跳转到最后一张克隆的第一张图片
					currentLeft = - PAGE_WIDTH * imgCount
			}
	}

	$list.css('left',currentLeft)

},ITEM_TIME);

循环滚动实现

...
 $next.click(function(){
		//  下一页
		nextPage(true)
 })
//每隔3s自动切换
var timer = setInterval(() => {
		 nextPage(true)
},3000)

//当鼠标进入图片区域时,自动停止,当鼠标离开,有开始自动切换
$container.hover(function(){
		//清除定时器
		clearInterval(timer)

},function(){
		//鼠标离开 开启定时器
		timer = setInterval(() => {
				nextPage(true)
		},3000)
})
...

使圆点高亮显示

...
 //获取图片数量
var imgCount = $dot.length
 //当前滚动图片的下标
var index = 0
...
...
$list.css('left',currentLeft)

		},ITEM_TIME);
		//更新圆点
		updatePoints(flag)
 }
 function updatePoints(flag){

		 //计算出目标圆点的下标targetIndex
		 var targetIndex = 0
		 //下一页使目标圆点下标+1
		 if(flag){
				targetIndex = index + 1 //[0 ,imgCount+1]
				if(targetIndex === imgCount){
						targetIndex = 0 
				}
		 }else{
				 targetIndex = index -1
				 if(targetIndex === -1){
						 targetIndex = imgCount-1
				 }
		 }
		//将当前index的<span>的class移除
		$dot.eq(index).removeClass('on')
		//给目标圆点添加class='on'
		$dot.eq(targetIndex).addClass('on')
		//将index更新为targetIndex
		index = targetIndex

 }
 ...

点击圆点实现图片滚动

...
//将index更新为targetIndex
	index = targetIndex
}
//点击圆点图片切换对应的图片
 $dot.click(function(){
		 //计算目标页的下标
		 var targetIndex = $(this).index()
		 if(targetIndex!=index){
				 //点击的不是当前页的圆点 才进行翻页
				 nextPage(targetIndex)
		 }
 })

这里我们将当前圆点的下标传入nextPage我们要对nextPage进行一部分修改,因为传进来的参数不止是boolean类型了,还有数字类型

 /**
 * true:下一页
 * false:上一页
 * 数值:指定下标页
 */
 function nextPage(flag){
		//设置偏移量
		var offset = 0
		if(typeof flag==='boolean'){
				offset = flag ? -PAGE_WIDTH : PAGE_WIDTH
		}else{
				offset = -(flag-index) * PAGE_WIDTH
		}
		...

更新圆点方法updatePoints也有修改

...
function updatePoints(flag){        
 //计算出目标圆点的下标targetIndex
 var targetIndex = 0
 if(typeof flag ==='boolean'){
		//下一页使目标圆点下标+1
		if(flag){
				targetIndex = index + 1 //[0 ,imgCount+1]
				if(targetIndex === imgCount){
						targetIndex = 0 
				}
		}else{
				targetIndex = index -1
				if(targetIndex === -1){
						targetIndex = imgCount-1
				}
		}
 }else{
	targetIndex = flag
 }
...

到此基本的轮播图实现完成,但是这里还有一个bug,当快速点击切换图片时会出现“空白的情况”
出现这种问题的原因是快速点击时触发了多个定时器进行移动

解决办法:只时一个定时器生效

 //当前滚动图片的下标
 var index = 0
 var moving = false  //翻页状态
 
 ...
 function nextPage(flag){
	if(moving)return  //如果正在翻页 直接结束
	moving = true //调用翻页时moving为true
	//设置偏移量
	var offset = 0
	if(typeof flag==='boolean'){
			offset = flag ? -PAGE_WIDTH : PAGE_WIDTH
	}else{
		offset = -(flag-index) * PAGE_WIDTH
}
...
//定时器循环滚动
var timer = setInterval(() => {
	currentLeft+=itemOffset
	if(currentLeft === targetLeft){
		clearInterval(timer)
		//标识翻页停止
		moving = false
 ...
 

个人博客上线欢迎来访 http://www.zihanzy.com

©️2020 CSDN 皮肤主题: 创作都市 设计师:CSDN官方博客 返回首页