实现简单的轮播图效果。
废话不多说,我们开始。
HTML和CSS较为简单,不在这里做赘述。简单的给大家一个HTML代码。
<div class="carousel"> <div id="goLeft"></div> <ul> <li><img src="" /></li> <li><img src="" /></li> <li><img src="" /></li> <li><img src="" /></li> </ul> <div id="goRigth"></div> <div class="down"></div> </div>
以下操作均是根据第一段代码所做的操作。
轮播图要怎们动,首先要明确思路,我们的需求是什么,其实很简单。我们需要是假如我们在点击goRight一次时,ul的依据自身向右偏移1个li的宽度的距离,点击两次时,依据自身偏移两个li宽度距离,以此类推。
但是我们需要思考一个问题,当我们移到第四张,下一次点击我们需要回到第一张,此时,ul向右移动了3个li宽度的距离,假设我们设置在ul的lefe为3个li宽度时,ul的left值为0,我们可以实现回到第一张,经过实践,会发现第四张图片会一瞬即逝,我们无法停留在第四张图片,这不是我们希望的,我们需要的是第四张图片依旧存在,但是又需要下次点击回到第一张图片。
理所应当我们有一个解决方法,我们先克隆一份第一个li内容,插入到li最后,我们结束第三次点击时,这时我们“身处”第四张图片,第四次点击时,我们会看到“第一张图片(这是我们提前拷贝好插入到最后的那个图片)”,此时我们看到的就是”第一张图片“,之后我们就悄悄的将ul的left值重置到最初的状态,即ul.style.left=0。(需要注意的是:当我们点击goLeft时,我们需要看到我们的倒数第二张图片,所有我们要将第一张图片拷贝添加后的倒数第二张图片也拷贝一次,添加到li最前面,这样我们在点击向左时,利用同样的方法,悄悄的将ul的left值在做修改就好了)。最后我们给ul添加一个过渡动画,这样看起来更加好看。
关于代码的详细思路:
1.先给左右两边的”按钮“添加监听事件,并判断动画是否完成。监听事件的函数我们传入一个 参数,以此判断我们时点击左边的还是右边的。并完成变量声明。
var goLeft = document.getElementById("goLeft"), goRight = document.getElementById("goRigth"), ul = document.getElementsByTagName("ul")[0], li = document.getElementsByTagName("li"), carousel = document.getElementsByClassName("carousel")[0], liWidth = li[0].offsetWidth, liLength = li.length, i = 1, //这里的i是判断ul偏移几个li的宽度的距离。 btn = true;
goRight.addEventListener("click", function() { if(btn) { go(‘rigth‘) } }); goLeft.addEventListener("click", function() { if(btn) { go(‘left‘) } });// btn按钮是我们提前定义的 var btn=true;
2.给监听事件的函数添加内容,首先我们需要先根据参数判断是点击左边还是右边的,当判断点击右边时,i++,当判断右边时,i--,同时给btn赋值false,最后给ul设置偏移量,为了良好的用户体验。
(以下两段代码在”function go(frow){}“中)。
frow == ‘rigth‘ ? i++ : i--; btn = false; ul.style.transform = ‘translateX(-‘ + i * liWidth + ‘px)‘; ul.style.transition = "all .5s ease";
3.判断临界值并执行阻断一次JS。
ul.addEventListener("transitionend", function() { // 本次点击动画完成后,重新赋值btn,并判断是否到达临界图片。 btn = true; if(i == liLength + 1) { // 向右点击,到达临界图片,取消ul动画,重新赋值i ul.style.transition = "none"; i = 1; } if(i == 0) { // 向左点击,到达临界图片,取消ul动画,重新赋值i ul.style.transition = "none"; i = liLength; } ul.style.transform = ‘translateX(-‘ + i * liWidth + ‘px)‘; //到达临界图片,悄悄改变ul.style.left getComputedStyle(ul).width; //阻断JS线程 (为什么,我也没懂暂时) ul.style.transition = "all .5s ease"; //重新给ul添加动画 })
至此,一个最基本的轮播图就做好了。
以下是完整代码(包含轮播图中小点控制图片)
HTML代码如下
<div class="carousel"> <div id="goLeft"></div> <ul> <li><img src="img/33.jpg" /></li> <li><img src="img/22.jpg" /></li> <li><img src="img/11.jpg" /></li> <li><img src="img/55.jpg" /></li> </ul> <div id="goRigth"></div> <div class="down"></div> </div>
CSS代码如下
div { width: 790px; height: 340px; position: relative; overflow: hidden; } ul { width: 9999px; height: 340px; font-size: 0; position: absolute; left: 0; list-style: none; } li { display: inline-block; } img { width: 100%; } #goLeft, #goRigth { width: 50px; height: 340px; background: rgba(0, 0, 0, 0.5); position: absolute; z-index: 99; } #goLeft { left: 0; } #goRigth { right: 0; } .down { display: flex; position: absolute; left: 355px; top: 305px; } .dot { width: 20px; height: 20px; background-image: url(img/icheck_red2.png); background-position: 161px 29px; margin-right: 3px; } .active { background-position: 117px 29px }
JS代码如下
//声明变量 var goLeft = document.getElementById("goLeft"), goRight = document.getElementById("goRigth"), ul = document.getElementsByTagName("ul")[0], li = document.getElementsByTagName("li"), carousel = document.getElementsByClassName("carousel")[0], liWidth = li[0].offsetWidth, liLength = li.length, i = 1, btn = true, dot = document.getElementsByClassName("dot"); //代码开始 ul.style.transform = ‘translateX(-‘ + i * liWidth + ‘px)‘; //克隆第一张图片插到最后,克隆最后一张图片插到最前面 var liFirst = li[0].cloneNode(true); ul.appendChild(liFirst); var liLast = li[liLength - 1].cloneNode(true); ul.insertBefore(liLast, li[0]); goRight.addEventListener("click", function() { if(btn) { go(‘rigth‘) } }); goLeft.addEventListener("click", function() { if(btn) { go(‘left‘) } }); function go(frow) { frow == ‘rigth‘ ? i++ : i--; btn = false; ul.style.transform = ‘translateX(-‘ + i * liWidth + ‘px)‘; ul.style.transition = "all .5s ease"; ul.addEventListener("transitionend", function() { for(var k = 0; k < liLength; k++) { dot[k].classList.remove("active") } // 这个循环是循环移除激活类 btn = true; if(i == liLength + 1) { ul.style.transition = "none"; i = 1; } if(i == 0) { ul.style.transition = "none"; i = liLength; } dot[i-1].classList.add("active"); //设置当前li添加激活类 ul.style.transform = ‘translateX(-‘ + i * liWidth + ‘px)‘; getComputedStyle(ul).width; ul.style.transition = "all .5s ease"; }) } //创建圆点 // var down = document.querySelector(".down"); //循环创建和图片数量相等的小点 for(let i = 0; i < liLength; i++) { down.innerHTML += "<div class=‘dot‘></div>" } //外层循环是循环给小点添加点击事件 var circles = document.querySelectorAll(".dot"); for(var m = 0; m < circles.length; m++) { circles[0].classList.add("active"); //给第一个小点最先添加一个激活类 (function(m) { circles[m].addEventListener("click", function() { for(var k = 0; k < circles.length; k++) { //内层循环清除所有小点的激活类 circles[k].classList.remove(‘active‘) } this.classList.add("active"); //给当前的小点添加激活类 ul.style.transform = "translateX(-" + (m + 1) * liWidth + "px)"; //点击小点,设置ul偏移量 ul.style.transition = ‘all .5s ease‘; //ul动画 i = m + 1; // 重点:将点击左右控制轮播图和点击小点控制轮播图联系起来,我们知道i是和第几张图片是一一对应的,i从1开始,m从0开始。既然要联系,那简单来说 }) // 就是用一个关系式把i和m联系起来,即i=m+1 })(m); }