一、实现的功能:
1. 进入页面,轮播图自动向右切换
2. 鼠标悬停在轮播图部分时,轮播图停止切换,鼠标离开继续自动切换
3. 鼠标悬停在下方的小圆点上时,自动切换到对应的图片
4. 鼠标点击向左或向右按钮时,图片会向左或向右切换
效果图如下:
二、无逢轮播图实现原理:
所谓无逢轮播,就是几张图片向左或者向右切换,使最后一张图片和第一张图片首尾相连
第一张图片和最后一张图片之间的切换,也像相邻的图片之间的切换一样,实现几张图片左右滚动切换的效果
那么,问题来了
怎样使第一张图片和最后一张图片首尾相边呢?
我是这样做的
首先,需要一个div容器来包裹这个轮播图部分,我给这个容器添加了类名carouselContainer,这个容器的宽度和高度设置为图片的宽度和高度,我设置的是500px* 300px,还需要设置一个属性:overflow : hidden;
然后需要一个ul标签来放置多张图片,ul标签的ID为carousel
ul标签中放置多个li标签,每个li标签中都有一个img标签,用来放置图片,这几个标签向左浮动,在实现图片切换的时候,只需要移动ul即可
这部分是重点!
如果有3张图片,那我需要4个li标签,前三个li标签中放的是这三张图片,最后一个li中放的是第一张图片
如果有4张图片,那就需要5个li标签,前4个li标签放的是这4张图片,最后一个li中放的是第一张图片 以此类推
在这里,我就以3张图片为例啦!
为了方便理解,画了个草图
首先,容器中显示的是第一张图片,即 索引为0的 粉色部分,(0、1、2、3分别代表几张图片的索引值)向右切换时显示的应该是0、1、2、0、1、2...
那么3有什么作用呢?
这里就是重点中的重点啦
当图片切换到2时,下一张是3,这时再切换时,切换到3
当前图片是3,3和1是同一张图征,再切换应该切换到2
如果当前图片是3,同时又要向右切换,我们就把整个ul的margin-left设置为0,然后再让整个ul向左移动,移动到1(这里我们以为看到的是第一张图片,其实是因为第一张图片和最后一张图片是一样的,我们这时看到的是最后一张图片)
如果当前图片是0,同时又要向左切换,我们就把整个ul的margin-left设置为3*每张图片的宽度,再让整个ul向右移动,移动到2
这样就实现了第一张图片和最后一张图片的首尾相连。
好了,原理就是这样了
三、具体的代码实现
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <title>无缝轮播图</title> <script src="https://lib.baomitu.com/jquery/3.4.1/jquery.js"></script> <style type="text/css"> * { margin: 0; padding: 0; } .container { width: 600px; margin: 0 auto; margin-top: 100px; text-align: center; } .carouselContainer { width: 500px; height: 300px; border: 1px solid #eee; margin: 0 auto; margin-top: 20px; overflow: hidden; position: relative; border-radius: 5px; } #carousel { font-size: 0px; display: flex; } .arrowItems { position: absolute; width: 100%; font-size: 60px; display: flex; top: 50%; justify-content: space-between; height: 60px; transform: translateY(-50%); } .arrowItems div { width: 30px; text-align: center; line-height: 46px; vertical-align: middle; background: rgba(0, 0, 0, 0.2); cursor: pointer; color: rgba(255, 255, 255, 0.4); } .arrowItems div:hover { background: rgba(0, 0, 0, 0.5); color: rgba(255, 255, 255, 0.6); } .dots { position: absolute; left: 50%; transform: translateX(-50%); bottom: 25px; background: rgba(255, 255, 255, 0.5); border-radius: 10px; padding: 3px; } .dot { width: 12px; height: 12px; background: #fff; float: left; border-radius: 6px; margin: 0 3px; } .current { background: red; } img{ width:500px; height:300px; } </style> </head> <body> <div class="container"> <h2>无缝轮播图</h2> <div class="carouselContainer"> <ul id="carousel"> <li><img src="001.jpg"></li> <li><img src="002.jpg"></li> <li><img src="003.jpg"></li> <li><img src="004.jpg"></li> <li><img src="005.jpg"></li> <li><img src="001.jpg"></li> </ul> <div class="arrowItems"> <div class="left">‹</div> <div class="right">›</div> </div> <div class="dots"> <div class="dot current"></div> <div class="dot"></div> <div class="dot"></div> <div class="dot"></div> <div class="dot"></div> </div> </div> </div> </body> <script type="text/javascript"> var picIndex = 0; //为小圆点绑定鼠标经过事件 $('.dots div').mouseover(function(){ picIndex = $(this).index(); var left = -(picIndex) * 500 + 'px'; //鼠标经过小圆点时,切换对应的图片 $('#carousel').stop().animate({'margin-left': left}); //当前小圆点为红色,其他为白色 $(this).addClass('current').siblings().removeClass('current'); }); //自动播放 autoplayCarousel(); var timeId; function autoplayCarousel(){ timeId = setInterval(function(){ $('.arrowItems .right').click(); }, 1000) } //右边按钮 $('.arrowItems .right').click(function(){ if(picIndex == $('#carousel li').length - 1) { picIndex = 0; $('#carousel').css({'margin-left': '0px'}); } picIndex ++; var left = -(picIndex) * 500 + 'px'; $('#carousel').stop().animate({'margin-left': left}); //控制小圆点 if(picIndex == $('#carousel li').length - 1) { $('.dots div').eq(0).addClass('current').siblings().removeClass('current'); }else { $('.dots div').eq(picIndex).addClass('current').siblings().removeClass('current'); } }); //左边按钮 $('.arrowItems .left').click(function(){ if(picIndex == 0) { picIndex = $('#carousel li').length - 1; $('#carousel').css({'margin-left': -($('#carousel li').length - 1) * 500 + 'px'}); } picIndex --; var left = -(picIndex) * 500 + 'px'; $('#carousel').stop().animate({'margin-left': left}); //控制小圆点 if(picIndex == $('#carousel li').length - 1) { $('.dots div').eq(0).addClass('current').siblings().removeClass('current'); }else { $('.dots div').eq(picIndex).addClass('current').siblings().removeClass('current'); } }); $('.carouselContainer').mouseover(function(){ clearInterval(timeId); }); $('.carouselContainer').mouseout(function(){ autoplayCarousel(); }); </script> </html>
四、在实现这个无逢轮播图地过程中也学到了一些知识,顺便记录下来
1. 子盒子在父盒子里面水平垂直居中
垂直居中:
以前的垂直居中用的都是设置子盒子top: 50%; margin-top为负的子盒子高度的一半
这个方法有局限性,如果以后子盒子的高度变了,还需要再改一次子盒子的margin-top值
现在发现了一个完美的方式来设置子盒子在父盒子里面垂直居中:
给子盒子设置top: 50%; transform: translateY(-50%);
top是相对于父盒子的高度设置的,transform是相对于子盒子自身的高度设置的,这样,以后父盒子、子盒子的高度不管怎样变化,子盒子都会在父盒子里面垂直居中
水平居中也是一样的,设置left: 50%; transform: translateX(-50%);
2. 动画要先停止再动
在使用jquery的animate动画时,如果多次触发动画,会出现动画错乱的现象,比如轮播图中的小圆点,如果鼠标一直在上面来回切换,图片就会左右乱动
出现这个现象的原因就是前一个动画还没停止,又要执行下一个动画
解决办法很简单,就是先让上一个动画停止再执行下一个动画,执行动画前先停止上一个动画
即代码中的$('#carousel').stop().animate({'margin-left': left});
加stop()就解决这个问题了
3. 清除定时器
在这个轮播图的例子中我设置了定时器来使图片自动播放,当鼠标悬停在轮播图区域时,需要停止自动播放,在鼠标离开轮播图区域时,再开始自动播放
做法就是在需要自动播放时,设置定时器,给定时器绑定一个ID,var timeId = setInterval(function(){}, 1000);
在需要停止的时候通过clearInterval(timeId);来清除计时器
再需要自动播放时再通过timeId = setInterval(function(){}, 1000);来实现自动播放
这里需要注意的是,这个timeId要设置成一个全局变量,否则,如果每次自动播放时都写成var timeId = setInterval(function(){}, 1000);这里的timeId是一个新的变量,清除计时器时清除的也不是同一个计时器,这样就会出现播放错乱的现象,所以要设置成一个全局变量。
4. 图片放在一起时会有逢隙
图片放在一起时,中间会有逢隙,比如轮播图中,我给ul标签中的li设置了float: left; 向左浮动,但是图片之间会有一个逢隙,这样不好控制图片的移动。
网上的解决办法有很多,在这里,我采用了最简单的解决办法,就是给父盒子设置,font-size: 0px;
这样,图片之间就没胡逢隙了。