面向对象-js原生轮播图-从零到一

js原生轮播图

  • 面向对象编程js原生实现轮播图效果
    • 1.先看效果图
    • 2.需要实现的功能:
    • 3.html结构
    • 4.功能实现
      • 4.1 创建对象
      • 4.2动画效果由translateX实现
      • 4.3根据轮播图片个数生成数字按钮节点
      • 4.4轮播图数字按钮点击切换状态
      • 4.5轮播事件,也是点击右箭头的事件
      • 4.6事件绑定
      • 4.7初始化方法
      • 4.8实例化Carousel对象,大功告成
    • 5备注

面向对象编程js原生实现轮播图效果

1.先看效果图

面向对象-js原生轮播图-从零到一_第1张图片

2.需要实现的功能:

  • 自动轮播
  • 点击左右箭头按钮无缝轮播
  • 点击数字按钮切换图片

分析:如何实现无缝轮播?
在一个固定大小的相框里有一个ul标签,其长度是几个图片宽度的总和,通过translateX()的方法来实现左右移动动画。
如何实现无缝呢?比如有三张图片,可以在把第一张图片通过cloneNode的方法克隆下来放到第三张图片后面。图片顺序 1,2,3,1,看下面的HTML结构,结构中并没有4张图,第四张图是生成的。

3.html结构


<div class="container">
    <div id="screen">
        <ul>
            <li><img src="./img/1.jpg" alt="">li>
            <li><img src="./img/2.jpg" alt="">li>
            <li><img src="./img/3.jpg" alt="">li>
        ul>
        <ol>
            
            
            
        ol>
    div>
    <div>
        <span><span>
        <span>>span>
    div>
div>

4.功能实现

4.1 创建对象

创建一个对象,需要传入一个相框盒子元素,通过这个元素来获取盒子中其他需要的元素,并把这些作为这个Carousel对象的属性:

function Carousel(el) {
    this.screen = el; // 相框
    this.width = this.screen.offsetWidth; // 相框宽度
    this.ulBox = this.screen.children[0]; // ul盒子
    this.list = this.ulBox.children; // ul下面所有li
    this.olBox = this.screen.children[1]; // 数字按钮盒子
    this.arrow = this.screen.nextElementSibling; // 箭头盒子
    this.leftArraw = this.arrow.children[0]; // 左箭头
    this.rightArraw = this.arrow.children[1]; // 右箭头
    this.index = 0; // 数字按钮的索引
    this.timeId = null; // 定时器的id
    this.activeClass = 'active'; // 数字按钮class名
    this.durtion = '.35s'; // 动画持续时间
}

4.2动画效果由translateX实现

// 动画
Carousel.prototype.animate = function (target) {
    this.ulBox.style.transform = 'translateX(' + target + 'px)'
};

4.3根据轮播图片个数生成数字按钮节点

生成节点后,为新生成的节点添加点击事件,实现每次点击根据节点对应的index切换图片,这里实现的需求的第三个功能。

// 创建节点
Carousel.prototype.createNodes = function () {
	let self = this;
	// 创建按钮节点
	for (let i = 0; i < self.list.length; i++) {
	    let liObj = document.createElement('li');
	    liObj.innerText = i + 1;
	    self.olBox.appendChild(liObj);
	
	    // 为生成的数字按钮添加点击事件
	    liObj.onclick = function () {
	        self.index = this.innerText - 1; // 获取当前点击对象的索引值
	        self.switch_sel();
	        self.animate(-self.index * self.width);
	    };
	}
    // 默认显示第一张图片,第一个数字按钮默认选中状态
    self.olBox.children[0].className = self.activeClass;
    // 克隆第一张图放到ulBox后面,实现无缝轮播
    self.ulBox.appendChild(self.ulBox.children[0].cloneNode(true));
};

4.4轮播图数字按钮点击切换状态

因为多次用到这段代码,所有就写成一个方法挂在Carousel对象上了

// 切换数字按钮的选中状态
Carousel.prototype.switch_sel = function(){
    let self = this;
    for (let i = 0; i < self.olBox.children.length; i++) {
        self.olBox.children[i].removeAttribute('class');
    }
    self.olBox.children[self.index].className = self.activeClass;
};

4.5轮播事件,也是点击右箭头的事件

// 轮播事件
Carousel.prototype.clickHandle = function () {
    let self = this;
    // 如果是最后一张图,直接跳到第一张
    if (self.index === self.list.length - 1) {
        self.index = 0;

        // 当点击到最后一张时直接跳到第一张
        self.ulBox.style.transitionDuration = '0s';
        self.animate(-self.index * self.width);
    }

    // 必须有时间延迟,否则图片跳转切换不成功,因为self.animate()没有来得及执行就被后面的self.animate()函数覆盖了。
    setTimeout(function () {
        self.ulBox.style.transitionDuration = self.durtion;
        self.index++;
        self.animate(-self.index * self.width);

        // 如果是最后一张图,则去掉最后一个的class属性,切换到第一个
        if (self.index === self.list.length - 1) {
            self.olBox.children[self.olBox.children.length - 1].removeAttribute('class');
            self.olBox.children[0].className = self.activeClass;
        } else { // 切换当前选中状态
            self.switch_sel();
        }
    }, 20);
};

4.6事件绑定

为左右箭头点击绑定事件,同时当鼠标hover在相框上时自动轮播取消,鼠标离开相框时自动轮播开始执行。

// 事件绑定
Carousel.prototype.bindEvent = function () {
    let self = this;
    // 又点击下一张
    self.rightArraw.onclick = function () {
        self.clickHandle();
    };
    // 左点击上一张
    self.leftArraw.onclick = function(){
        if(self.index === 0){
            self.index = self.list.length - 1;

            // 直接跳到最后一张
            self.ulBox.style.transitionDuration = '0s';
            self.animate(-self.index * self.width);
        }

        setTimeout(function(){
            self.ulBox.style.transitionDuration = self.durtion;
            self.index--;
            self.animate(-self.index * self.width);
            self.switch_sel();
        }, 20);
    };

    // 鼠标悬停清除定时器
    self.screen.parentElement.onmouseover = function(){
        self.timeId && clearInterval(self.timeId);
        self.arrow.style.display = 'flex';

    };
    // 鼠标离开打开定时器
    self.screen.parentElement.onmouseout = function(){
        self.timeId = setInterval(self.clickHandle.bind(self), 2000);
        self.arrow.style.display = 'none';
    }
};

4.7初始化方法

初始化方法中创建节点,绑定事件,同时设定定时器实现自动轮播效果。

// 初始化
Carousel.prototype.init = function () {
    this.createNodes();
    this.bindEvent();
    this.timeId = setInterval(this.clickHandle.bind(this), 2000);
    // 注意这里要bind(this) 否则clickHandle中的this指向window
};

4.8实例化Carousel对象,大功告成

实例化一个轮播图对象,然后调该对象的init方法。
只要html结构相同,只需要传入不同的相框元素,就可以在同一个页面中实例化多个轮播图对象。也就是说,同一个页面的多处轮播效果。

let carousel = new Carousel(document.getElementById('screen'));
carousel.init();

5备注

全部的代码和css样式可参考我的github中的轮播图仓库,菜鸟程序猿一枚,程序设计如果有不妥的地方欢迎提出意见或建议,当然啦,如果你喜欢并star了我的这个仓库,我会很开心的 : )
[1]: https://github.com/jiangleiundo/carousel

你可能感兴趣的:(JavaScript)