美文网首页让前端飞
利用jquery实现轮播图-e6写法

利用jquery实现轮播图-e6写法

作者: 家里有棵核桃树 | 来源:发表于2019-01-02 15:26 被阅读1次

    用了好久bootstrap提供的轮播图插件,刚好最近很闲,就自己实现轮播图效果练练手。bootstrap较早的版本都是利用原型的办法(有些也用了es6的proxy)实现的,最新的版本用的是es6的类(class)和一些模块的思想来实现。本文实现轮播效果的方法和bootstrap的实现不一样,但是会借鉴相关的代码风格。由于是练手demo在轮播插件的封装上考虑的不是太多。

    1、使用

    1.1 静态资源

    使用js前要提前引用jquery,可以把该js文件放在</body>前引用。

    1.2 HTML模板

    把内容按如下格式装填好后,就可以出现轮播效果了(跟bootstrap类似)。轮播项的格式要和指示器的个数一一对应,轮播项和指示器缺一不可。

    <!--carousel 轮播容器-->
    <div class="carousel">
        <!--carousel-inner 每一个轮播项内容-->
        <div class="carousel-inner">
            <div class="carousel-item active" data-index="0">
                <a href="#">
                    <img class="carousel-img" src="img/1.png" alt="">
                </a>
                <div class="carousel-caption">
                    <h3>HEADER 1~</h3>
                </div>
            </div>
            ...
        </div>
    
        <!--carousel-indicators 指示器,指示当前显示的是第几项 也可以点击切换当前的显示项-->
        <ul class="carousel-indicators">
            <li class="active" data-index="0">1</li>
            <li data-index="1">2</li>
            <li data-index="2">3</li>
            <li data-index="3">4</li>
            <li data-index="4">5</li>
        </ul>
    
        <!--carousel-ctrl* 左右箭头,可上下切换当前的显示项【可省略】-->
        <span class="carousel-ctrlPrev">&lt;</span>
        <span class="carousel-ctrlNext">&gt;</span>
    </div>
    

    1.3 效果

    轮播呈现
    功能:
    • 动态循环轮播
    • 上下切换
    • 点击跳转指定项

    2、实现

    2.1 轮播设计思想

    (1)下一张的操作
        让当前项的下一张显示出来,然后通过jquery提供的animate方法将盒子左移一个盒子的宽度(left: -盒子宽度;),移动效果完成后,将最开始显示的那一项隐藏且设置当前盒子的左移大小为0(left: 0;)。
        如果当前项没有下一张,那么就把第一张插入到当前项的后面。再继续上面的操作。

    (2)上一张的操作
        让当前项的上一张显示出来,设置盒子的左移大小为一个盒子的宽度(left: -盒子宽度;),然后通过jquery提供的animate方法将盒子的左移大小设置为0(left: 0;),移动效果完成后,将最开始显示的那一项隐藏。
        如果当前项没有上一张,那么就把最后一张插入到当前项的前面。再继续上面的操作。

    (3)指示器指定显示项
        先拿到显示项的序号,再判断滚动方向(next还是prev),通过滚动方向来确定下一项是插入到当前项的后面还是前面,继续上一张或下一张的操作。

    2.2 代码

    (1)js

    // 用到的轮播图的相关模块
    const Selector = {
        BOX: '.carousel',
        INNER: '.carousel-inner',
        ACTIVE: '.active',
        ACTIVE_ITEM: '.active.carousel-item',
        ITEM: '.carousel-item',
        NEXT: '.carousel-ctrlNext',
        PREV: '.carousel-ctrlPrev',
        INDICATORS: '.carousel-indicators',
    };
    
    // 轮播框大小
    const Box = {
        WIDTH: $(Selector.BOX).width(),
        HEIGHT: $(Selector.BOX).height()
    };
    
    // 相关类名
    const ClassName = {
        ACTIVE : 'active'
    };
    
    // 方向
    const Direction = {
        NEXT: 'next',
        PREV: 'prev'
    };
    
    // 默认配置
    const Default = {
        interval: 3000,
        gap: 600
    };
    
    class Carousel {
        constructor(selector, config) {
    
            this._isPaused = false;
            this._interval = null;
            this._enableClickAction = true;
            this._activeElement = $(Selector.ACTIVE_ITEM);
            this._targetElement = null;
            this._element = $(selector);
            this._inner = $(Selector.INNER);
            this._indicatorsElement = $(Selector.INDICATORS);
    
            this._init();
        }
    
        pause() {
    
            this._isPaused = true;
            clearInterval(this._interval);
        }
    
        cycle() {
    
            this._isPaused = false;
            if (this._interval) {
                // 重新开始轮播时 要重新更新定时器 不然显示有误差,因为有多个定时器存在
                clearInterval(this._interval);
                this._interval = null;
            }
            this._interval = setInterval(() => this._slide('next'), Default.interval);
        }
    
        _init() {
    
            this._addEventListeners();
            this.cycle();
        }
    
        _addEventListeners() {
    
            // 下一页
            $(Selector.NEXT).on('click', () => this._slide('next'));
            // 上一页
            $(Selector.PREV).on('click', () => this._slide('prev'));
            // 鼠标移入轮播暂停
            $(Selector.BOX).on('mouseenter', () => this.pause());
            // 鼠标移除轮播继续
            $(Selector.BOX).on('mouseleave', () => this.cycle());
            // 轮播框框被点击切换时 阻止过快点击出现的问题
            $(Selector.BOX).on('click', () => {
    
                if (this._enableClickAction) {
                    this._enableClickAction = false;
                    setTimeout(() => this._enableClickAction = true, Default.gap);
                }
            });
            // 指示器点击时 切换到对应的图片
            $(Selector.INDICATORS).on('click', 'li', event => this._slide('', $(event.target)));
        }
    
        _getActiveItemIndex() {
            return this._activeElement.data('index');
        }
    
        _getTargetItemIndex($indicator = null, direction = 'next') {
    
            if ($indicator) {
                return $indicator.data('index');
            } else {
                let itemsLength = $(Selector.ITEM).length;
                let index = Direction.NEXT == direction ? this._getActiveItemIndex() + 1 : this._getActiveItemIndex() - 1;
                itemsLength == index && (index = 0);
                -1 == index && (index = itemsLength - 1);
                return index;
            }
        }
    
        _isActiveItemOnEdge(direction) {
    
            let $items = this._inner.find(Selector.ITEM);
            return Direction.NEXT == direction
                ? this._activeElement[0] == $items.last()[0]
                : this._activeElement[0] == $items.first()[0];
        }
    
        _setActiveIndicatorElement() {
    
            this._indicatorsElement
                .find(Selector.ACTIVE).removeClass(ClassName.ACTIVE)
                .end()
                .find(`[data-index='${this._getActiveItemIndex()}']`).addClass(ClassName.ACTIVE);
        }
    
        // $indicator 只有通过指示器改变轮播图才会用到
        _slide(direction = 'next', $indicator = null) {
    
            // 如果在短时间内多次点击 不进行任何操作
            if(!this._enableClickAction) return false;
    
            // 当轮播图开始滚动时 得到当前项和需要滚动到的指定目标项
            this._activeElement = $(Selector.ACTIVE_ITEM);
            this._targetElement = this._inner.find(`${Selector.ITEM}[data-index='${this._getTargetItemIndex($indicator, direction)}']`);
    
            // 根据方向 将targetElement插入到对应的位置
            $indicator && (direction =  this._getTargetItemIndex($indicator) > this._getActiveItemIndex() ? 'next' : 'prev');
    
            // 需要将目标项显示出来
            this._targetElement.addClass('active');
    
            // 根据不同的prev、next操作 判断是否需要改变列表排列顺序
            let isActiveItemOnEdge = this._isActiveItemOnEdge(direction);
            if (Direction.NEXT == direction && (isActiveItemOnEdge || $indicator)) {
    
                // 将第一项放到最后一项
                this._targetElement.appendTo(this._inner);
            }
            if (Direction.PREV == direction) {
    
                // 将最后一项放到第一项,原始的盒子inner的left需要修改
                (isActiveItemOnEdge || $indicator) && this._targetElement.prependTo(this._inner);
                this._inner.css('left', -Box.WIDTH);
            }
    
            // 切换轮播图的显示
            this._inner.animate({
                left: Direction.NEXT == direction ? -Box.WIDTH : 0
            }, Default.gap, 'linear',() => {
    
                // 轮播图切换成功后的操作
                this._activeElement.removeClass('active');
                this._activeElement = this._targetElement;
                this._inner.css('left', 0);
    
                // 修改对应的指示器
                this._setActiveIndicatorElement();
            });
        }
    
        static _jQueryInterface(config) {
            return new Carousel(this, config);
        }
    }
    
    // new Carousel(Selector.BOX);
    $.fn.carousel = Carousel._jQueryInterface;
    $.fn.carousel.Constructor = Carousel;
    
    $('.carousel').carousel();
    

    (2)less

    * {
      margin: 0;
      padding: 0;
    }
    @carouselWidth: 500px;
    @carouselHeight: 300px;
    .container {
      box-sizing: content-box;
      width: @carouselWidth;
      height: @carouselHeight;
      padding: 10px;
      margin: 100px auto;
      border: 1px solid #ccc;
    }
    .carousel {
      position: relative;
      width: @carouselWidth;
      height: @carouselHeight;
      overflow: hidden;
      color: #666;
    }
    .carousel-inner{
      position: absolute;
      width: 200%;
      height: 100%;
    }
    .carousel-item {
      display: none;
      width: @carouselWidth;
      height: @carouselHeight;
      float: left;
      &.active {
        display: block;
      }
    }
    .carousel-caption {
      position: absolute;
      bottom: 0;
      width: 100%;
      height: 50px;
      padding: 0 10px;
      background: rgba(0, 0, 0, 0.2);
      line-height: 50px;
    }
    .carousel-img {
      width: 100%;
      height: 100%;
    }
    .carousel-indicators {
      position: absolute;
      right: 10px;
      bottom: 10px;
      text-align: center;
      li {
        display: inline-block;
        height: 20px;
        width: 20px;
        margin: 3px;
        border-radius: 10px;
        background-color: rgba(0, 0, 0, 0.3);
        font-size: 13px;
        line-height: 20px;
        cursor: pointer;
        &.active {
          background-color: rgba(0, 0, 0, 0.6);
          color: #bbb;
        }
      }
    }
    
    [class*='carousel-ctrl'] {
      position: absolute;
      top: 50%;
      width: 40px;
      height: 40px;
      border: 1px solid #fff;
      background: #fff;
      color: #000;
      opacity: 0.1;
      font-family: '黑体';
      font-weight: bold;
      font-size: 30px;
      text-align: center;
      line-height: 40px;
      transform: translateY(-50%);
      cursor: pointer;
      &:hover {
        opacity: 0.5;
      }
    }
    .carousel-ctrlPrev {
      left: 5px;
    }
    .carousel-ctrlNext {
      right: 5px;
    }
    

    (3)html

    <!DOCTYPE html>
    <html lang="zh-cn">
    <head>
        <meta charset="UTF-8">
        <title>轮播图</title>
        <link href="css/007.css" rel="stylesheet"> <!--记得替换-->
        <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
        <script src="js/007.js" defer></script> <!--记得替换-->
    </head>
    <body>
    <div class="container">
        <!--carousel 轮播容器-->
        <div class="carousel">
            <!--carousel-inner 每一个轮播项内容-->
            <div class="carousel-inner">
                <div class="carousel-item active" data-index="0">
                    <a href="#">
                        <img class="carousel-img" src="img/1.png" alt="">
                    </a>
                    <div class="carousel-caption">
                        <h3>HEADER 1~</h3>
                    </div>
                </div>
                <div class="carousel-item" data-index="1">
                    <a href="#">
                        <img class="carousel-img" src="img/2.png" alt="">
                    </a>
                    <div class="carousel-caption">
                        <h3>HEADER 2~</h3>
                    </div>
                </div>
                <div class="carousel-item" data-index="2">
                    <a href="#">
                        <img class="carousel-img" src="img/3.png" alt="">
                    </a>
                    <div class="carousel-caption">
                        <h3>HEADER 3~</h3>
                    </div>
                </div>
                <div class="carousel-item" data-index="3">
                    <a href="#">
                        <img class="carousel-img" src="img/4.png" alt="">
                    </a>
                    <div class="carousel-caption">
                        <h3>HEADER 4~</h3>
                    </div>
                </div>
                <div class="carousel-item" data-index="4">
                    <a href="#">
                        <img class="carousel-img" src="img/5.png" alt="">
                    </a>
                    <div class="carousel-caption">
                        <h3>HEADER 5~</h3>
                    </div>
                </div>
            </div>
    
            <!--carousel-indicators 指示器,指示当前显示的是第几项 也可以点击切换当前的显示项-->
            <ul class="carousel-indicators">
                <li class="active" data-index="0">1</li>
                <li data-index="1">2</li>
                <li data-index="2">3</li>
                <li data-index="3">4</li>
                <li data-index="4">5</li>
            </ul>
    
            <!--carousel-ctrl* 左右箭头,可上下切换当前的显示项-->
            <span class="carousel-ctrlPrev">&lt;</span>
            <span class="carousel-ctrlNext">&gt;</span>
        </div>
    </div>
    </body>
    </html>
    

    相关文章

      网友评论

        本文标题:利用jquery实现轮播图-e6写法

        本文链接:https://www.haomeiwen.com/subject/bixzlqtx.html