做为一个前端工程师,不管公司是什么行业,不管你作什么端,基本都会遇到一个避不开的动画效果:循环轮播。作轮播并不难,市场上的轮播插件有不少,其中比较著名的是swiper,使用也很是简单。但轮播插件这种东西总归是不灵活的,一些简单的场景还能够应付,比较复杂一点的场景处理起来就比较麻烦了。今天我会全程带你们来写一个循环轮播,用到的技术有:html、css、JavaScript、jQuery,都是前端最基础的技术,有基础又爱学肯学的你必定一听就会,若是不会咋整?那多看几遍。😆javascript
以小米官网的图片轮播为例,实际上千篇一概,好啦,看下图:css
好啦,看效果,不要看妹子,虽然妹子长得是很好看啦!html
无限循环轮播的原理是在展现内容的先后各放一组图片,以无限循环展现3张照片为例,三张图片我给它取名为1.jpg,2.jpg,3.jpg,图片展现分别以下:前端
原理示意图展现:java
原理其实就是复制两组一样的照片分别放在前面和后面(实际上不用彻底复制两组,只须要前面能够到1.jpg,后面也能够到1.jpg就行了,但这里我为了方便你们理解,就采用这样的方式了)。当点左边按钮,图片轮播到第一张1.jpg时,让盛放图片的容器瞬间拉回到第二张1.jpg照片的位置,注意必定要是瞬间。同理,当点右边按钮时,图片轮播到第三张1.jpg的时候,也让盛放图片的容器瞬间拉回到第二张1.jpg照片的位置。这是实现图片循环轮播的关键,稍后会仔细讲解。web
html代码:前端工程师
<div class="slideImageContainer"> <div class="slideImageLists"> <img src="1.jpeg" /> <img src="2.jpeg" /> <img src="3.jpeg" /> <img src="1.jpeg" /> <img src="2.jpeg" /> <img src="3.jpeg" /> <img src="1.jpeg" /> <img src="2.jpeg" /> <img src="3.jpeg" /> </div> <div class="slideLeftBtn" id="slideLeftBtn"></div> <div class="slideRightBtn" id="slideRightBtn"></div> </div>
css 代码:ide
*{ padding: 0; margin: 0; } @font-face { font-family: 'iconfont'; /* project id 208314 */ src: url('//at.alicdn.com/t/font_208314_2l9oi1sn4hmh1tt9.eot'); src: url('//at.alicdn.com/t/font_208314_2l9oi1sn4hmh1tt9.eot?#iefix') format('embedded-opentype'), url('//at.alicdn.com/t/font_208314_2l9oi1sn4hmh1tt9.woff') format('woff'), url('//at.alicdn.com/t/font_208314_2l9oi1sn4hmh1tt9.ttf') format('truetype'), url('//at.alicdn.com/t/font_208314_2l9oi1sn4hmh1tt9.svg#iconfont') format('svg'); } .slideImageContainer{ position: relative; width: 600px; height: 300px; margin: 0 auto; border: solid 1px red; overflow: hidden; } .slideImageLists{ position: absolute; left: -1800px; top: 0; width: 10000px; height: 300px; } .slideImageLists img{ display: block; width: 600px; height: 300px; } .slideLeftBtn,.slideRightBtn{ position: absolute; font-family: "iconfont"; font-size: 60px; top: 120px; color: #191f25; opacity: 0.3; cursor: pointer;
user-select: none;
-webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; } .slideLeftBtn:hover,.slideRightBtn:hover{ opacity: 0.6; } .slideLeftBtn{ left: 10px; } .slideRightBtn{ right: 10px; }
页面布局是很重要的一部份内容,它是页面的基石。页面布局写得好实现效果的时候能带来很大的方便。所以这里强调几个应该注意的地方:svg
1. 全部的图片要放在一个很长的容器中,这里是slideImageList,每次移动实际上就是它在相对于他的父元素slideImageContainer而移动,因此须要给slideImageContainer 一个 position:relative 的定位,给 slideImageList 一个 position: absoluete 的定位。函数
2. slideImageList要放在一个比较小的容器中,在这里是slideImageContainer,做用是为了显示你想要显示的区域,注意要加 overflow:hidden 属性,让多余的内容不显示。
3. 左右按钮我采用的是iconfont的使用方式,这个比较简单,此处很少加以阐述。不会使用iconfont的同窗能够直接贴两个图片或者左右箭头符号在上面。
4. 容器slideImageList中的图片要排列在一条直线上,而且初始状况下须要给slideImageList一个left值,由于最开始咱们想让第四张照片展现,因此此时的left值为-1800px,要记住这个值,由于咱们待会儿要经常使用到这个值。
5. @font-face 是引入 iconfont 相关的资源内容,不使用iconfont的可忽略。
接下来看javascript代码:
var slideIndex = 3; //记录初始图片的下标( 默认最初展现第四张图片,下标从0开始,因此初始值为3 ) //左边按钮的点击事件 $("#slideLeftBtn").on("click",function(){ // 点击左按钮的时候想要显示当前图片的前一张,因此slideIndex值要减去1 slideIndex--; // animateLength表示想要让slideImageLists移动到什么位置,slideImageLists 的位置由 left属性来控制 var animateLength = slideIndex * (-600) + "px"; $(".slideImageLists").animate({"left":animateLength},"slow",function(){ // animate的回调函数(即执行完动画以后才会执行函数里面的内容) if(slideIndex <= 0){ $(".slideImageLists").css({"left":"-1800px"}); slideIndex = 3; } }); }) //右边按钮的点击事件 $("#slideRightBtn").on("click",function(){ // 点击右按钮的时候想要显示当前图片的后一张,因此slideIndex值要加上1 slideIndex++; var animateLength = slideIndex * (-600) + "px"; $(".slideImageLists").animate({"left":animateLength},"slow",function(){ if(slideIndex >= 6){ $(".slideImageLists").css({"left":"-1800px"}); slideIndex = 3; } }) })
如今着重来分析一下JavaScript的代码,一样有几个关键点须要注意,其中部分我已在代码中注释:
1. 全局变量 slideIndex 指的是图片的下标,一共有九张照片,下标从0开始,因此九张照片的下标值分别为0-8,此处咱们默认展现第四张照片,因此slideIndex 的初始值置为 3 。另外须要注意的是,slideIndex 是全局变量,因此函数内函数外均可以访问到,而且只初始化一次。
2. 局部变量 animateLength 指的是想要 slideImageLists 运动到的位置,注意要加单位,而且须要赋值给 slideImageList 的 left 属性。
3. jQuery的 animate 方法 ,详情见下图:
接下来完整的分析一下流程,以点击左按钮为例:
1. 初始状况下展现第四张图片,下标为 3 。 ( var slideIndex = 3 )
2. 给左按钮绑定一个点击事件
3. 点击左按钮的时候,想要展现当前照片的前一张,因此图片下标须要减去1 ( slideIndex-- )
4. 计算 slideImageLists 要移动的位置 ( slideIndex * (-600) + "px" ),记得加单位。为何要乘以 -600 ,首先 600 是一张照片的宽度,上面咱们分析过了若是要默认展现第四张照片的话 slideImageLists 的 left 属性值为 -1800px,同理,点击左按钮,想要展现第三张照片,那么此时须要 slideImageLists 的 left 属性值为 -1200px,因此就是 ( 3 - 1 ) * ( -600 ) + "px" = -1200px 。
5. 利用 animate 来执行动画。将上一步计算出来的值赋值给 slideImageLists 的 left 属性。注意 animate方法自己就是含有过渡的,因此切记不须要在 slideImageLists 上面再加 transtion 属性来实现过渡。
6. 实现循环轮播的重点来了。以上步骤实现了轮播,但没有实现循环轮播,回忆咱们刚才讲的内容,一共有三组 1.jpg、2.jpg、3.jpg 的照片,默认展现第四张照片,也就是第二组照片中的 1.jpg ,若是点击左按钮,会分别展现第一组照片中的 3.jpg 、2.jpg、1.jpg , 假设一直点击左按钮,展现到第一张照片,也就是第一组的 1.jpg 的时候,此时图片的下标 slideIndex 的值为 0 。当此时展现的图片的下标 slideIndex 的值为 0 而且执行完这个动画的时候,咱们须要作一个操做,将 slideImageLists 的 left 值瞬间改变为 -1800px,这个值咱们上面强调过了,是初始状况下展现第四张照片也就是第二组中的 1.jpg 的时候 slideImageLists 的 left 值,而且将当前展现的图片的下标 slideIndex 的值变为 3 。
animate有一个很是方便的地方在于他提供了一个回调函数,回调函数在动画执行完以后本身执行。
另外,这里还有一个须要格外注意的地方,咱们一直强调必定要瞬间将 slideImageLists 拉回到 left 值为 -1800px 的地方,那是由于若是也相似于用animate来实现的话用户会看到一个动画的过程,这是咱们不能接受的。因此在瞬间拉回的时候我采用的是jQuery的css方法去改变 left 属性。
可是讲到这里,实际上仍是有不完美的地方,若是你屡次点击按钮,就会发生错乱,此时咱们须要作的是在动画的执行过程当中点击按钮无效,只有动画结束完成才能够继续点击实现动画。我这里采用的方案是引入一个布尔类型的变量 isClickable,初始值为true,表示初始状况下可点击。当用户点击按钮的时候会进行判断当前 isClickable 的值,若是值为true的时候才会去执行 slideIndex-- 的操做,不然会 return false ,不会再执行下面的代码。
此时咱们来分析一下流程:
1. 初始状况下isClickable的值为true,表示当前按钮是能够点击的。
2. 此时咱们去点击左按钮,isClickable 的值为 true , 会执行slideIndex-- 的操做。而且将 isClickable的值设置为 false,表示如今已经处在动画中。此时再去点击左按钮就没法再执行slideIndex--的操做,而是进入 return false,终止当前代码。
3. 须要注意的是,咱们须要在动画执行完成后,也就是在回调函数中将 isClickable 的值变为 true,因此当动画结束后再点击按钮的时候就能够进行下一次动画了。
具体代码以下:
var isClickable = true; // 是否可点击,默承认点击 var slideIndex = 3; $("#slideLeftBtn").on("click",function(){ if(isClickable == true){ slideIndex--; }else{ return false; } isClickable = false; var animateLength = slideIndex * (-600) + "px"; $(".slideImageLists").animate({"left":animateLength},"slow",function(){ isClickable = true; if(slideIndex <= 0){ $(".slideImageLists").css({"left":"-1800px"}); slideIndex = 3; } }); })