纯原生JS写封装左右无缝链接轮播图插件(完整代码及注释,可参考可直接使用)

(前言:小编也是一个刚入行的小白,所以写不出来多么高深的东西,若有错误欢迎指证或者其他的什么相互验证,但是不接受大神的鄙视,谢谢,转载请注明出路)

  1. 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等都可以进行自行更改自己喜欢的样式,只要不该元素结构以及类名等,当然如果你可以明白其中原理就都可以更改了)

  2. 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=`
    ${(this.data.length+1)*this.width}px">`,strUl=`
      `,str; for(let i=0;i<this.data.length;i++){ strDiv+=`
      ${this.imgPrefix}${this.data[i].img}" width="${this.width}" height="${this.height}">
      `
      ; strUl+=`
    • ${i==0?'select':''}" style="width: ${this.width/800*12}px;height: ${this.width/800*12}px">
    • `
      } strDiv+=`
      ${this.imgPrefix}${this.data[0].img}" width="${this.width}" height="${this.height}">
      `
      ; strDiv+=`
    `
    ; strUl+=`` //根据传入的是否需要左右按钮切换而判断是否需要添加左右按钮 if(this.isArrow){str=strDiv+strUl+`${this.width/800*50}px;height: ${this.width/800*50}px">${this.width/800*50}px;height: ${this.width/800*50}px">`}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使用了面向对象思想的类来进行的插件封装,可根据参数注释来进行自行调整)

  3. HTML

    
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Titletitle>
    <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一个插件对象进行传参即可)

你可能感兴趣的:(javascript)