JS的面向对象实例--轮播图

实现轮播图的方法有很多种,本篇是通过同时控制两个索引(要走的,要进来的)的方式让图片动起来

结构部分


//展现图片的空间
//放轮播图所有图片
//按钮部分

css代码


js代码

class Banner{
    constructor(){
        this.left = document.getElementById("left");
        this.right = document.getElementById("right");
        this.child = document.querySelectorAll(".imgbox a");
        this.list = document.querySelector(".list");
        this.box = document.querySelector(".box");

        this.iNow = 0;
        this.iPrev = this.child.length - 1;
    }
    init(){
        var that = this;
        this.left.addEventListener("click",function(){
            that.changeIndex(1);
        })
        this.right.addEventListener("click",function(){
            that.changeIndex(-1);
        })
        //事件委托绑定事件
        this.list.onclick = function(eve){
            var e = eve || window.event;
            var tar = e.target || e.srcElement;
            if(tar.tagName == "SPAN"){
                //触发事件时,执行改变索引,同时将点前点击的span传入
                that.listChangeIndex(tar);
            }
        }
    }
    changeIndex(direct){
        if(direct == 1){
            if(this.iNow == 0){
                this.iNow = this.child.length-1;
                this.iPrev = 0;
            }else{
                this.iNow--;
                this.iPrev = this.iNow + 1;
            }
        }else{
            if(this.iNow == this.child.length-1){
                this.iNow = 0;
                this.iPrev = this.child.length-1;
            }else{
                this.iNow++;
                this.iPrev = this.iNow - 1;
            }
        }
        this.move(direct);
    }
    move(direct){
        // 根据左右按钮传入的状态:左1,右-1
        // 利用乘法
        // 改变不同按钮的方向问题
        this.child[this.iPrev].style.left = 0;
        move(this.child[this.iPrev],{left:this.child[0].offsetWidth * direct});
        this.child[this.iNow].style.left = -this.child[0].offsetWidth * direct + "px";
        move(this.child[this.iNow],{left:0});

        this.setActive();
    }
    createList(){
        //创建对应图片数量的span,同时编号
        var str = ``;
        for(var i=0;i${i+1}`;
        }
        this.list.innerHTML = str;

        //设置默认的当前项
        this.setActive();
    }
    setActive(){
        for(var i=0;i this.iNow){
            //向左运动
            this.listMove(1,index);
        }
        // 判断方向
        if(index < this.iNow){
            // 向右运动
            this.listMove(-1,index);
        }

        //将当前点击的索引设置成下次要走的索引
        this.iNow = index;

        // 根据修改之后的索引,设置当前项
        this.setActive();
    }
    listMove(direct,index){
        // this.iNow走
            // 从哪走,走到哪
        this.child[this.iNow].style.left = 0;
        move(this.child[this.iNow],{left:-1000 * direct})
        // index进来
            // 从哪进来,进到哪
        this.child[index].style.left = 1000 * direct + "px";
        move(this.child[index],{left:0});
    }
    autoPlay(){
        var t = setInterval(()=>{
            this.changeIndex(-1);
        },2000)

        this.box.onmouseover = function(){
            clearInterval(t);
        }

        var that = this;
        this.box.onmouseout = function(){
            t = setInterval(()=>{
                that.changeIndex(-1);
            },2000)
        }
        
    }
}


var b = new Banner();
b.init();
b.createList();
b.autoPlay();

其中引入的封装函数move

// 参数是要控制的元素 参数2是对象,在使用之前需要解析(遍历)
function move(ele,obj,cb){
clearInterval(ele.t);
ele.t = setInterval(() => {
    // 假设状态为:可以清除计时器
    var i = true;
    // 因为在计时器中才开始使用到对象中的信息,所以在计时器中遍历
    // 并提前换来的属性和目标变量
    for(var attr in obj){
        if(attr == "opacity"){
            var iNow = getStyle(ele,attr) * 100;
        }else{
            var iNow = parseInt(getStyle(ele,attr));
        }

        let speed = (obj[attr] - iNow)/10;
        speed = speed < 0 ? Math.floor(speed) : Math.ceil(speed);
        // 只要有一个属性到目标,就停了,不对
        // 必须所有属性到目标,才能停

        // 只要有一个属性没到目标,绝对不能停
            // 用状态来标记到底要不要停止计时器

        // 只要有一个属性没到目标:绝对不能清除计时器
        if(iNow !== obj[attr]){
            i = false;
        }
        if(attr == "opacity"){
            ele.style.opacity = (iNow + speed)/100;
        }else{
            ele.style[attr] = iNow + speed + "px";
        }
    }
    // 如果每次计时器执行结束,所有属性都执行了一遍之后,状态还是true,表示,没有被改成false,如果没有被改成false,表示没有属性没到终点,那么状态还是false就不清除
    if(i){
        clearInterval(ele.t);
        // 用户决定在动画结束时要执行的功能,万一用户没传参,做个默认判断
        if(cb){
            cb();
        }
        // cb && cb();
    }
}, 30);
}
function getStyle(ele,attr){
if(ele.currentStyle){
    return ele.currentStyle[attr];
}else{
    return getComputedStyle(ele,false)[attr];
}
}

你可能感兴趣的:(JS的面向对象实例--轮播图)