(前言:小编也是一个刚入行的小白,所以写不出来多么高深的东西,若有错误欢迎指证或者其他的什么相互验证,但是不接受大神的鄙视,谢谢,转载请注明出路)
-
css
body,div,ul,li,a,p{ margin: 0; padding: 0; -webkit-user-select: none; } li{ list-style: none; } .Banner1{ margin: 20px auto; overflow: hidden; position: relative; } .Banner1>div:nth-of-type(1){ position: absolute; } .Banner1>div:nth-of-type(1)>div{ float: left; } .Banner1>ul{ position: absolute; left: 42%; bottom: 20px; border-radius: 10px; padding: 4px; } .Banner1>ul>li{ margin-left:1px; float: left; border-radius: 50%; border: 1px solid #CCCCCC; cursor: pointer; } .Banner1>ul>li.select{ background-color: #9ba0ad; } .Banner1>a{ position: absolute; border-radius: 50%; opacity: .8; display: none; cursor: pointer; background-size: 100% 100%; top: 45%; } .Banner1>a:nth-of-type(1){ left: 3%; background: url("../img/左箭头-填充 (1).png") no-repeat ; background-size: 100% 100%; } .Banner1>a:nth-of-type(2){ right: 3%; background: url("../img/右箭头-填充.png") no-repeat; background-size: 100% 100%; }
(css中存放非宽高大小的样式,左右箭头图片以及li小按钮样式可以自行调整自己喜欢的样式,以及其他的left,bottom等都可以进行自行更改自己喜欢的样式,只要不该元素结构以及类名等,当然如果你可以明白其中原理就都可以更改了)
-
JS
~function () { class Banner1{ // options是传入的参数对象,没传为空对象 constructor(options={}){ //解构传入的对象 let { ele, //传入的容器对象 data,//需要绑定的json对象数据 url, //请求数据的API接口地址 isArrow=true, //是否支持左右切换 isFocus=true, //是否支持焦点切换 isAuto=true, //是否支持自动切换 interval=3000, //切换间隔速度 moveEnd, //切换完成后需要处理的事情 width=800, //ele的宽度,默认800px,必须是能整除20的数 height=400, //ele的高度,默认400px imgPrefix='' //图片前缀 }=options; // 将这些属性都挂载到实例中去 ['ele', 'url', 'isArrow', 'isFocus', 'isAuto', 'interval', 'moveEnd','width','height','data','imgPrefix'].forEach(item => { //item是一个字符串,而我们需要的是同名的变量,所以可以使用eval将字符串变成同名变量 this[item] = eval(item); }); //调用init主入口开启轮播图 this.init(); } //Bander的主入口init,规化方法的执行顺序 init(){ let p; /** * 浏览器的最大最小显隐会对setinterval定时器有暂停的影响,所以需要对浏览器的显隐进行处理 * document.onvisibilitychange监听浏览器窗口的显隐行为,最小化的时候其document.visibilityState属性会变成'hidden' * 这个时候我们就要清楚掉定时器,不然后出现定时器乱了的现象,当再次显示浏览器窗口时就再将定时器加上 */ document.onvisibilitychange= ()=> { if(document.visibilityState==='hidden'){ clearInterval(this.times); }else{ this.autoMove(); } } //传有数据就不在去请求数据了,没传才会去请求 if(!this.data){ //this.data没传就是undefined =》!fasle =true;就去请求数据 p=this.queryData(); }else{ //this.data传了有的话就不去请求数据了 p=new Promise((resolve, reject) =>{resolve()}); } p.then(()=>{ //进行数据绑定 this.bindHtml() },()=>{console.log('数据请求失败');return}).then(()=>{ if(this.isAuto){ this.autoMove(); } if(this.eAs){ this.btnMove(); } if(this.isFocus){ this.focusMove(); } }) } //请求数据 queryData(){ let {url}=this; return new Promise((resolve,reject)=>{ let xhr=new XMLHttpRequest(); xhr.open('get',url); xhr.onreadystatechange=()=>{ if(xhr.readyState===4&&xhr.status===200){ this.data=JSON.parse(xhr.responseText); resolve(); } if(xhr.status!=200){ reject(); } } xhr.send(); }) } //绑定数据 bindHtml(){ //由于考虑到复用的效果,所以在绑定数据的同时将所以盒子的宽高都进行了一个计算添加,这样我们传入的宽高参数是多少,这个轮播图的整体大小就是多少,其中所有元素都会按比例进行缩放 //为父盒子添加样式(有部分不涉及宽高的样式就可以直接写在css中去,不需要动态生成) this.ele.className="Banner1"; //为父盒子设置我们传进来的宽高 this.ele.style.width=/^(-)?\d+(\.\d+)?(px|rem|em)?$/.test(this.width)?/(px|rem|em)$/.test(this.width)?this.width:this.width+'px':'800px'; this.ele.style.height=/^(-)?\d+(\.\d+)?(px|rem|em)?$/.test(this.height)?/(px|rem|em)$/.test(this.height)?this.height:this.height+'px':'800px'; //生成模板字符串 let strDiv=`<div style="width:${(this.data.length+1)*this.width}px">`,strUl=`<ul>`,str; for(let i=0;i<this.data.length;i++){ strDiv+=`<div><img src="${this.imgPrefix}${this.data[i].img}" width="${this.width}" height="${this.height}"></div>`; strUl+=`<li class="${i==0?'select':''}" style="width: ${this.width/800*12}px;height: ${this.width/800*12}px"></li>` } strDiv+=`<div><img src="${this.imgPrefix}${this.data[0].img}" width="${this.width}" height="${this.height}"></div>`; strDiv+=`</div>`; strUl+=`</ul>` //根据传入的是否需要左右按钮切换而判断是否需要添加左右按钮 if(this.isArrow){str=strDiv+strUl+`<a class="leftBtn" style="width: ${this.width/800*50}px;height: ${this.width/800*50}px"></a><a class="rightBtn" style="width: ${this.width/800*50}px;height: ${this.width/800*50}px"></a>`}else{str=strDiv+strUl} //渲染页面 this.ele.innerHTML=str; //获取到移动的div和所有的li以及两个左右按钮 this.eDiv=this.ele.getElementsByTagName('div')[0]; this.eLis=this.ele.getElementsByTagName('ul')[0].getElementsByTagName('li'); this.eAs=this.ele.getElementsByTagName('a'); //标识当前显示图片索引 this.liIndex=0; //标识图片切换是否完成,避免上一次动画切换未完成用户又触发下一次动画 this.bool=false; } //自动轮播 autoMove(){ this.times=setInterval( ()=>{ let eLeft=parseFloat(getComputedStyle(this.eDiv)['left']),left=0; let time=setInterval(()=>{ left-=this.width/800*20; this.eDiv.style.left=eLeft+left+'px'; if(left<=-parseFloat(this.width)){ clearTimeout(time); this.liIndex++; if(this.liIndex===this.eLis.length){ this.liIndex=0; this.eDiv.style.left='0px'; } this.changeCss(); } },this.width/800*17) },this.interval) //鼠标移入期间停止轮播 this.ele.onmouseover=()=>{ //显示左右小箭头 clearTimeout(this.times) if(this.eAs){ [].forEach.call(this.eAs,(item)=>{ item.style.display='block'; }) } } //鼠标移出开始轮播 this.ele.onmouseout=()=>{ this.autoMove(); if(this.eAs){ [].forEach.call(this.eAs,(item)=>{ item.style.display='none'; }) } } } //支持左右按钮切换 btnMove(){ for(let i=0;i<this.eAs.length;i++){ this.eAs[i].onclick=()=>{ if(this.bool) return; this.bool=true; //当单机左右按钮的时候,只需要清理定时器就可以,不需要再加上,因为按钮单机的时候会触发鼠标移入移出事件,鼠标移出事件会加上自动切换 clearInterval(this.times); if(i===0) { let eLeft = parseFloat(getComputedStyle(this.eDiv)['left']), left = 0; eLeft=eLeft==0?(this.liIndex=this.eLis.length-1,this.eLis.length*-this.width):(this.liIndex-=1,eLeft); let btnTime = setInterval(() => { left += this.width/800*20; this.eDiv.style.left = eLeft + left + 'px'; if (left >= this.width) { clearInterval(btnTime); this.changeCss(); this.bool=false; } }, this.width/800*17) }else{ let eLeft = parseFloat(getComputedStyle(this.eDiv)['left']), left = 0; let btnTime = setInterval(() => { left -= this.width/800*20; this.eDiv.style.left = eLeft + left + 'px'; if (left <= -this.width) { clearInterval(btnTime); this.liIndex++; if(this.liIndex===this.eLis.length){ this.liIndex=0; this.eDiv.style.left='0px'; } this.changeCss(); this.bool=false; } }, this.width/800*17) } } } } //支持焦点切换 focusMove(){ [].forEach.call(this.eLis,(item,index)=>{ item.onclick=()=>{ clearInterval(this.times) if(this.liIndex===index)return; this.liIndex=index; this.eDiv.style.left=index*-this.width+'px'; this.changeCss(); } }) } //切换li样式 changeCss(){ [].forEach.call(this.eLis,(item,index)=>{ if(index!==this.liIndex){ item.className=''; }else{ item.className='select'; } }) } } //挂载全局 window.Banner={ Banner1 }; }();
(JS使用了面向对象思想的类来进行的插件封装,可根据参数注释来进行自行调整)
-
HTML
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="xxx.css"> </head> <body> <div id="box"></div> <script src="xxx.js"></script> <script> let box=document.getElementById('box'); //将数据放入data new Banner.Banner1({ele:box, data:[ {img:'//img.alicdn.com/tps/TB1_2OWLVXXXXcTXVXXXXXXXXXX-1130-500.jpg'}, {img:'//img.alicdn.com/tps/TB1Lw9SLVXXXXajaXXXXXXXXXXX-1130-500.jpg'}, {img:'//img.alicdn.com/tps/TB1QyGZLVXXXXa9XVXXXXXXXXXX-1130-500.jpg'}] ,width:800,height:400}); //数据使用url请求得来 // new Banner.Banner1({ele:box,url:'../json/newList.json',width:800,height:400,imgPrefix:'../'}); </script> </body> </html>
(html中引入上面的css以及js,然后new一个插件对象进行传参即可)