需求:
1. 点击左右箭头切换图片
2. 点击标题切换对应的图片
3. 实现无缝循环切换 (所谓无缝轮播就是最后一张图片和第一张图片连接起来,实际上是给我们造成一种视觉假象)
4. 封装函数,方便以后使用
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <title>Document</title> 7 <style> 8 .box{width: 1130px;height: 300px;margin: 20px auto;position: relative; 9 overflow: hidden; 10 } 11 .imgbox{height: 300px;position: absolute;left:0;} 12 .imgbox a{float: left;} 13 .imgbox img{width: 1130px;height: 300px;} 14 15 </style> 16 </head> 17 <body> 18 <div class="box"> 19 <div class="imgbox"> 20 <a><img src="https://img.zcool.cn/community/013c185ec5e1a0a801214d72ae5567.jpg" alt=""></a> 21 <a><img src="https://img.zcool.cn/community/019b5a5ec5ea6ba801209b864afbad.png" alt=""></a> 22 <a><img src="https://img.zcool.cn/community/0155475ec5ea82a801209b86526dc0.png" alt=""></a> 23 <a><img src="https://img.zcool.cn/community/0133395ec5ea9fa801209b86533992.png" alt=""></a> 24 <a><img src="https://img.zcool.cn/community/013c185ec5e1a0a801214d72ae5567.jpg" alt=""></a> 25 </div> 26 </div> 27 </body> 28 <script> 29 // 可自定义的轮播图 30 class Banner{ 31 constructor(ops){ 32 // 处理参数 33 this.imgbox = ops.imgbox; 34 this.list = ops.list!==false ? true : false; 35 this.btn = ops.btn!==false ? true : false; 36 this.autoPlay = ops.autoPlay!==false ? true : false; 37 // 默认索引 38 this.index = 0; 39 // 获取所有图片 40 this.items = this.imgbox.children; 41 42 // 功能1. 初始化布局:完善imgbox的宽度 43 this.init(); 44 // 功能B. 根据参数决定是否创建按键 45 this.isBtn(); 46 // 功能L. 根据参数决定是否创建list 47 this.isList(); 48 // 功能A. 根据参数决定是否需要自动播放 49 this.isAutoPlay(); 50 } 51 init(){ 52 this.imgbox.style.width = this.items.length * this.items[0].offsetWidth + "px"; 53 } 54 isAutoPlay(){ 55 // A1.如果是false,终止当前函数,不执行后面代码,不做这个功能 56 if(!this.autoPlay) return; 57 // 如果执行到此处,说明上面过来的是true,没有执行return 58 59 // A2.立即开启计时器,执行点击右按钮要做的事情 60 this.t = setInterval(() => { 61 // 右按钮被点击时要执行的函数 62 this.changeIndex(-1); 63 }, 2000); 64 65 var that = this; 66 // A3.鼠标进入停止 67 this.imgbox.parentNode.onmouseover = function(){ 68 clearInterval(that.t); 69 } 70 // A4.鼠标离开继续 71 this.imgbox.parentNode.onmouseout = function(){ 72 that.t = setInterval(() => { 73 that.changeIndex(-1); 74 }, 2000); 75 } 76 } 77 isList(){ 78 // L1.如果是false,终止当前函数,不执行后面代码,不做这个功能 79 if(!this.list) return; 80 // 如果执行到此处,说明上面过来的是true,没有执行return 81 82 // L2.为了实现无缝轮播,将第一张图复制了一遍多了一张,记得去掉 83 var num = this.items.length-1; 84 // 假设的图片的名字,将来必然是数据 85 var arr = ["体彩","彩墨画","洗剪吹","网页设计"]; 86 // L3.创建list的容器 87 this.list = document.createElement("div"); 88 this.list.style.cssText = `position: absolute;width: 100%;height: 40px;line-height: 40px;display: flex;bottom: 0;left:0;text-align: center;`; 89 // L4.根据图片的数量,创建对应个span 90 var str = ""; 91 for(var i=0;i<num;i++){ 92 str += `<span key=${i} style="flex: 1;margin: 0 1px;background: rgba(200,200,200,0.6)">${arr[i]}</span>`; 93 } 94 // L5.将span放在list容器中 95 this.list.innerHTML = str; 96 // 设置索引对应span的当前项 97 this.list.children[this.index].style.background = "green"; 98 // L6.将list容器插入页面 99 this.imgbox.parentNode.appendChild(this.list); 100 101 // L7.绑定list中span的事件 102 this.listAddEvent(); 103 } 104 listAddEvent(){ 105 var that = this; 106 var aspan = this.list.children; 107 for(var i=0;i<aspan.length;i++){ 108 aspan[i].onclick = function(){ 109 // L8.获取span身上的索引:保证索引的数据是数值,防止将来出现问题 110 that.index = parseInt(this.getAttribute("key")); 111 // L9.执行move,显示对应图片 112 that.move(); 113 // L11.修改当前背景色 114 that.setActive() 115 } 116 } 117 } 118 setActive(){ 119 // 取消所有 120 for(var i=0;i<this.list.children.length;i++){ 121 this.list.children[i].style.background = "rgba(200,200,200,0.6)"; 122 } 123 // 为了处理最后一张图(其实就是复制的第一张图)的索引,单独判断,保存变量 124 // 计算索引 125 var k = this.index===this.items.length-1 ? 0 : this.index; 126 // 设置当前索引对应的span的背景色 127 this.list.children[k].style.background = "green"; 128 } 129 isBtn(){ 130 // B1.如果是false,终止当前函数,不执行后面代码,不做这个功能 131 if(!this.btn) return; 132 // 如果执行到此处,说明上面过来的是true,没有执行return 133 134 // B2.创建并插入左按钮 135 this.left = document.createElement("input"); 136 this.left.style.cssText = `width: 40px;height: 40px;background: rgba(200,200,200,0.6);border:none;position: absolute;top:130px;left:0`; 137 this.left.value = "<" 138 this.imgbox.parentNode.appendChild(this.left); 139 140 // 创建并插入右按钮 141 this.right = document.createElement("input"); 142 this.right.style.cssText = `width: 40px;height: 40px;background: rgba(200,200,200,0.6);border:none;position: absolute;top:130px;right:0`; 143 this.right.value = ">"; 144 this.imgbox.parentNode.appendChild(this.right); 145 146 this.left.type = this.right.type = "button"; 147 148 // B3.绑定左右按钮的点击事件 149 this.btnAddEvent(); 150 } 151 btnAddEvent(){ 152 var that = this; 153 this.left.onclick = function(){ 154 // B4-1.改变索引 155 that.changeIndex(1) 156 } 157 this.right.onclick = function(){ 158 // B4-2.改变索引 159 that.changeIndex(-1); 160 } 161 } 162 changeIndex(d){ 163 if(d===1){ 164 if(this.index===0){ 165 this.index = this.items.length-2; 166 this.imgbox.style.left = -(this.items.length-1) * this.items[0].offsetWidth + "px"; 167 }else{ 168 this.index--; 169 } 170 }else{ 171 if(this.index===this.items.length-1){ 172 this.index = 1; 173 this.imgbox.style.left = 0; 174 }else{ 175 this.index++; 176 } 177 } 178 // B5.移动大框,切换图片 179 this.move(); 180 // L12.点击按钮时,设置索引对应的list的span的背景色 181 // 设置之前先判断,list出否存在,不存在,不设置样式 182 this.list && this.setActive(); 183 } 184 move(){ 185 // B6.显示图片 186 // L10.显示图片 187 // 神器:console.log 188 // console.log(this.index); 189 move(this.imgbox, {left: -this.index*this.items[0].offsetWidth}); 190 } 191 } 192 193 // 准备执行方式 194 new Banner({ 195 imgbox:document.querySelector(".box .imgbox"), // 必传 196 list:true, // 可选,默认为true 197 btn:true, // 可选,默认为true 198 autoPlay:false // 可选,默认为true 199 }) 200 201 202 function move(ele, data, cb) { 203 clearInterval(ele.t); 204 ele.t = setInterval(() => { 205 var onoff = true; 206 207 for (var i in data) { 208 var iNow = parseInt(getStyle(ele, i)); 209 210 var speed = (data[i] - iNow) / 8; 211 speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed); 212 213 ele.style[i] = iNow + speed + "px"; 214 215 if (iNow != data[i]) { 216 onoff = false; 217 } 218 } 219 if (onoff) { 220 clearInterval(ele.t); 221 // 结束的位置要做什么,交给使用者决定 222 // 传个功能进来,传函数 223 cb && cb(); 224 } 225 }, 30); 226 } 227 // 获取样式的兼容处理 228 function getStyle(ele, attr) { 229 if (ele.currentStyle) { 230 return ele.currentStyle[attr]; 231 } else { 232 return getComputedStyle(ele, false)[attr]; 233 } 234 } 235 </script> 236 </html>
欢迎各位宝宝留言!!!