效果展示:
思路:
1.构建轮播图首先需要布局,布局可以帮助我们更加清楚当前得步骤,方便整理思路
2.本次案例中我用的是构造函数-面向对象编程,按需求,不断地细节化,不断拆分,拆分成可以直接实现地需求,然后面对对象地设计,通过精密的协作,达到高内聚,低耦合的效果
3.面向对象的分析:OOA
a.点击左右键 ,获取当前的索引
b 改变当前的索引,改变图片的索引
c 根据索引,改变样式
4.面向对象的设计和编程:OOD和OOP
页面布局的设计
<div class="banner"> <div class="box"> <a href="#"><img src="https://img.zcool.cn/community/015d475f4dc28211013f1a64f13ddf.png@1280w_1l_2o_100sh.png" alt=""></a> <a href="#"><img src="https://img.zcool.cn/community/0177315f3e4275a801215aa0b4afc5.png@1280w_1l_2o_100sh.png" alt=""></a> <a href="#"><img src="https://img.zcool.cn/community/018fa85dcd1c49a8012129e24d41a4.png@1280w_1l_2o_100sh.png" alt=""></a> <a href="#"><img src="https://img.zcool.cn/community/0170e45dca7870a8012163ba31bbb4.png@1280w_1l_2o_100sh.png" alt=""></a> </div> <span class="left"><i class="iconfont icon-arrow-right"></i></span> <span class="right"><i class="iconfont icon-arrow-left-copy"></i></span> <div class="btn"> <b class="active">1</b> <b>2</b> <b>3</b> <b>4</b> </div>css样式的设计
<link rel="stylesheet" href="font/iconfont.css"> <style> .banner{ width: 1000px; height: 500px; position: relative; margin: 100px auto; border: 1px solid black; overflow: hidden; } .box{ width: 1000px; height: 500px; position: absolute; } a{ position: absolute; display: block; width: 1000px; height: 500px; text-decoration: none; } a img{ position: absolute; left: 1000px; width: 1000px; height: 500px; } a:nth-child(1) img{ left: 0px; } span { position: absolute; width: 50px; height: 50px; line-height: 50px; text-align: center; top: 225px; font-size: 30px; background-color: darkkhaki; opacity: 0.5; display: flex; } .left{ left: 0px; } .right{ right: 0px; } .icon-arrow-left-copy{ text-align: center; margin-right: 20px; line-height: 50px; } .icon-arrow-right{ margin-left: 20px; line-height: 50px; text-align: center; } .btn{ position: absolute; left: 0px; bottom: 0px; width: 100%; height: 50px; display: flex; text-align: center; line-height: 50px; color: #000; } .btn b{ flex: 1; margin: 0 5px; background-color: rgba(100, 75, 123, 0.6); } .btn b.active{ background-color: royalblue; opacity: 0.7; } </style>JS核心代码
<script> //构造函数 function Banner(){ //获取样式 将该属性放到构造函数中 this.obox=document.querySelector(".box"); this.aimg=document.querySelectorAll("img"); this.left=document.querySelector(".left"); this.right=document.querySelector(".right"); this.ab=document.querySelectorAll("b"); //因为是两个方向的改变,需要设置两个方向的索引 //设置进的索引 this.index=0; //设置出的索引 不确定 this.Preindex=NaN; //触发当前函数的执行 this.addEvent(); } Banner.prototype={ addEvent:function(){ //当添加了点击事件以后,内外this不再是指向同一个this var that=this; //左点击,触发一个索引改变的事件 this.left.onclick=function(){ that.changeIndex(-1);//这个地方的传参,是方便后面的判断左右点击 that.setStyle(that.index);//同时设置按钮的样式 } //右点击 触发一个索引改变事件 this.right.onclick=function(){ that.changeIndex(1); that.setStyle(that.index); } //方便设置按钮与图片的对应 for(var i=0;i<this.ab.length;i++){ //给索引添加一个xuhao属性,方便判断 this.ab[i].xuhao=i; this.ab[i].onclick=function(){ console.log("点击的索引"+this.xuhao); console.log("当前的索引是"+that.index); //比较 that.compare(this); that.setStyle(this.xuhao); } } }, compare:function(Anow){ //当前索引大于点击索引 图片往右走 if(this.index>Anow.xuhao){ this.leave(1,Anow); }else{ //点击索引大于当前索引,图片往左走 this.leave(-1,Anow); } }, leave:function(d,Anow){ this.aimg[this.index].style.left=0; //1000 move(this.aimg[this.index],{left:this.aimg[0].offsetWidth*d}); this.aimg[Anow.xuhao].style.left=-this.aimg[0].offsetWidth*d+"px"; move(this.aimg[Anow.xuhao],{left:0}); this.index=Anow.xuhao; }, setStyle:function(m){ for(var i=0;i<this.ab.length;i++){ this.ab[i].className=""; } this.ab[m].className="active"; }, changeIndex:function(d){ if(d===-1){ if(this.index===0){ this.index=this.aimg.length-1; this.Preindex=0; }else{ this.index--; this.Preindex=this.index+1; } console.log(this.Preindex,this.index); }else{ if(this.index===this.aimg.length-1){ this.index=0; this.Preindex=this.aimg.length-1; }else{ this.index++; this.Preindex=this.index-1; } console.log(this.Preindex,this.index); } this.changeImg(d); }, changeImg:function(d){ // //d传值为正负,当传入的是正值时,代表点击右边的按钮 this.aimg[this.Preindex].style.left=0; move(this.aimg[this.Preindex],{left:-1000*d}); this.aimg[this.index].style.left=1000*d+"px"; move(this.aimg[this.index],{left:0}); } } new Banner(); </script>JS核心代码的分析
1.分为左右点击两个按钮,为了区别左右按钮的点击,触发的图片索引的改变方向不同,传入了两个不同的参数,1和-1(这里为了后续的简化代码)
2.设置第一张图片为初始状态,left:0;剩余的图片在第一张图片的左边,即left:1000;
3.我们假想,每进来一张,便出去一张,要考虑这个往哪出,从哪进,这个方向很重要!
4.在点击右按钮时,设置的是this.index++;this.preindex=this.index-1;点击右键,图片往左走(这个时候将css样式的overflow:hidden取消,方便分析)走的是当前索引的上一个,紧来的是当前索引的下一个;
5.点击左按钮时,设置的是this.index--;this.preindex=this.index+1;点击左键,图片往右走,走的是当前索引的下一个,进来的是当前索引的上一个;
6.要单要设置一个临界点,就是图片的第一张和最后一张,这两张之间进行转换,注意!
7.设置move移动动画时我引入了一个我之前封装的函数,第一个变量设置当前要变的元素对象,第二个传的是对象,对象是要改变的属性。这里设置的是left,在-1000,0,1000这三个数之间,根据情况设置;
function move(ele,data,cb){ clearInterval(ele.t); //将元素作为对象存储数据 ele.t=setInterval(()=>{ //设计一个计数器,记录是否该清除计时器 var onOff=true; //默认是清 //遍历对象 for in for(var i in data){ //i 就是对应的键值 属性名 if(i==="opacity"){ var Anow=getStyle(ele,i)*100; }else{ var Anow=parseInt(getStyle(ele,i)); } //tar 是i对应的值 var speed=(data[i]-Anow)/10; speed =speed>0? Math.ceil(speed) :Math.floor(speed); //只要有一个没有达到目标 计数器将状态改为不清 if(data[i]!=Anow){ onOff=false; } if(data[i]==="opacity"){ ele.style.opacity=(Anow+speed)/100; }else{ ele.style[i]=Anow+speed+"px"; } } //循环遍历完,如果没有被改成false,说明达到目标,清除计时器 if(onOff){ clearInterval(ele.t); // 当前计时器清除意味着,当前运动结束,开启下一个功能了 // 下一个功能的内容,取决于用户的传参 // 执行之前要判断,用户是否传参,没传不执行 cb && cb(); } },30) } function getStyle(ele,attr){ if(ele.currentStyle){ return ele.currentStyle.attr; }else{ return getComputedStyle(ele,null)[attr]; } }如有不理解的,可以留言或私信