mobile轮播组件——支持事件回调和队列(原生js实现)

mobile轮播组件,支持图片不定高,支持事件回调,队列,兼容主流webkit浏览器

demo地址:http://7li.github.io/components/swipe/

demo二维码:技术分享

测试地址:http://7li.github.io/components/swipe/test/

仓库地址:https://github.com/7LI/swipe


本文出自:http://blog.csdn.net/nancle/article/details/44937531

  仓促之际必有疏漏,请各位同仁批评指正


源码

/*
 * Swipe 1.0.0
 *
 * Liu Yanzhi
 * 702368372atqqcom
 * Copyright 2015, MIT License
 * 
 * Thanks to: https://github.com/thebird
 */
define(function() {
  var TEST = document.getElementById('test');
  function test(str) {
    TEST.innerHTML = str;
  }
  function Swipe(container, option) {
    this.container = container;
    this.wrap = this.container.children[0];
    this.slides = this.wrap.children;
    this.length = this.slides.length;

    if (!option) option = {};
    this.option = option;
    this.speed = option.speed || 300;
    this.threshould = option.threshould || 90;
    this.auto = option.auto || 2000;
    this.index = 0;
    this.offset = 0;
    this.classes = {
      nav: 'swipe-nav',
      navItem: 'swipe-nav-item',
      navOn: 'swipe-nav-item-on'
    };
    this.queue = [];

    this.setup(); 
    this.bind();

    this.set('nav', option.nav !== false);
    this.set('auto', option.auto !== 0);
  }

  Swipe.prototype.setup = function() {
    this.width = this.container.offsetWidth;

    // Set container
    this.container.style.overflow = 'hidden';
    this.container.style.position = 'relative';

    // Set wrap
    this.wrap.style.position = 'relative';
    this.wrap.style.overflow = 'visible';
    this.wrap.style.height = 'auto';
    // this.wrap.style.width = '99999999px';
    this.wrap.style.webkitTransform = '';

    // Set slides   
    for(var i = 0; i < this.length; i++) {
      var slide = this.slides[i];
      slide.style.position = 'relative';
      slide.style.float = 'left';
      slide.style.height = 'auto';
      slide.style.width = this.width + 'px';
      slide.offset = i * this.width;
      slide.style.webkitTransform = '';
    }
  }

  Swipe.prototype.slideTo = function(index, callback, direction, queue) {
    // Handling muti-arguments
    if (index > this.length - 1) index = this.length - 1;
    if (index < 0) index = 0;
    if (typeof callback != 'function' && callback != null) {
      queue = direction;
      direction = callback;
      callback = null;
    };
    if (typeof direction != 'string') {
      queue = direction;
      direction = 'right';
    }

    // Not sliding and not enqueue, so do nothing
    if (this.sliding && !queue) return;

    // Sliding, so enqueque
    if (this.sliding && queue) {
      var slide = {
        index: index,
        callback: callback,
        direction: direction
      }
      this.queue.push(slide);
      return;
    }

    // Not sliding, so enforce slide
    if (index == this.index) {
      // Current index, no need to transition, immediately trigger callback
      callback && callback();
      this.nav && this.setNav();
      this.dequeue();
      return;
    }

    this.sliding = true;
    this.callback = callback;

    var offset;
    // Relocate slides
    this.relocateSlides(direction);
    // Relocate wrap
    offset =  this.slides[this.index].offset - this.slides[index].offset;
    offset += this.offset;

    this.offset = offset;
    this.index = index;

    var style = this.wrap.style;
    style.webkitTransitionDuration = this.speed + 'ms';
    style.webkitTransform = 'translate3D(' + offset + 'px, 0px, 0px)';
  }

  Swipe.prototype.relocateSlides = function(direction) {
    var currentSlide = this.slides[this.index];
    for (var i = 0; i < this.length; i++) {
      if (i == this.index) continue;

      var slide = this.slides[i];
      if (direction == 'right') {
        if (slide.offset < currentSlide.offset) {
          slide.offset += this.width * this.length;
          var calculateOffset = slide.offset - this.width * i;
          slide.style.webkitTransitionDuration = 0;
          slide.style.webkitTransform = 'translate3D(' + calculateOffset + 'px, 0px, 0px)';
        }
      } else if (direction == 'left') {
        if (slide.offset > currentSlide.offset) {
          slide.offset -= this.width * this.length;
          var calculateOffset = slide.offset - this.width * i;
          slide.style.webkitTransitionDuration = 0;
          slide.style.webkitTransform = 'translate3D(' + calculateOffset + 'px, 0px, 0px)';
        }
      }
    }
  }

  Swipe.prototype.prev = function(callback, queue) {
    // Handling muti-arguments
    if (typeof callback != 'function') { queue = callback; callback = null };

    var index = this.getIndex(queue);
    if (index <= 0) {
      index = this.length - 1;
    } else {
      index = index - 1;
    }
    this.slideTo(index, callback, 'left', queue);
  }

  Swipe.prototype.next = function(callback, queue) {
    // Handling muti-arguments
    if (typeof callback != 'function') { queue = callback; callback = null };

    var index = this.getIndex(queue);
    if (index >= this.length - 1) {
      index = 0;
    } else {
      index = index + 1;
    }

    this.slideTo(index, callback, 'right', queue);
  }

  Swipe.prototype.stop = function() {
    return this;
  }

  Swipe.prototype.bind = function() {
    var that = this;
    var start, delta;
    this.events = {
      handleEvent: function(e) {
        switch (e.type) {
            case 'touchstart':
              var touches = e.touches[0];
              start = {
                x: touches.pageX,
                y: touches.pageY,
              };
              delta = {x: 0, y: 0};
              that.container.addEventListener('touchmove', that.events);
              that.wrap.addEventListener('touchend', that.events);
              that.autoplay(false);
              break;
            case 'touchmove':
              // prevent native scrolling
              e.preventDefault();

              var touches = e.touches[0];
              delta = {
                x: touches.pageX - start.x,
                y: touches.pageY - start.y
              }
              var direction = delta.x > 0 ? 'left' : 'right';
              that.relocateSlides(direction);
              that.attempSlide(delta);
              break;
            case 'touchend': 
              if (Math.abs(delta.x) > that.threshould) {
                if (delta.x > 0) {
                  that.prev();
                } else {
                  that.next();
                }
              } else {
                that.cancelSlide();
              }
              that.container.removeEventListener('touchmove', that.events);
              that.container.removeEventListener('touchend', that.events);
              that.autoplay(that.option.auto !== 0);
              break;
            case 'transitionend':
            case 'webkitTransitionEnd':
              if (e.propertyName != '-webkit-transform' && 
                  e.propertyName != 'transform') return;

              that.sliding = false;
              that.nav && that.setNav(); // Set nav
              that.callback && that.callback();
              // Enforce the next slide in queue
              that.dequeue();
              break;
            case 'resize':
              that.resize();
            break;
         }
      }
    }
    this.container.addEventListener('transitionend', this.events, false);
    this.container.addEventListener('webkitTransitionEnd', this.events, false);
    this.container.addEventListener('touchstart', this.events);
    window.addEventListener('resize', this.events);
  }

  Swipe.prototype.resize = function() {
    this.setup();
    this.relocateSlides('right');
    // Relocate wrap
    this.offset =  -this.slides[this.index].offset;
    var style = this.wrap.style;
    style.webkitTransitionDuration = '0ms';
    style.webkitTransform = 'translate3D(' + this.offset + 'px, 0px, 0px)';
  }

  Swipe.prototype.dequeue = function() {
     var nextSlide = this.queue.shift();
     nextSlide && this.slideTo(nextSlide.index, nextSlide.callback);
  }

  Swipe.prototype.getIndex = function(queue) {
    var index = this.index;
    if (queue) {
      var lastSlide = this.queue[this.queue.length - 1];
      if (lastSlide) index = lastSlide.index;
    };
    return index;
  }

  Swipe.prototype.set = function(key, value) {
    switch (key) {
      case 'nav':
        if (!this.nav) {
          this.createNav();
        } 
        if (value == true) {
          this.nav.style.display = 'block';
          this.setNav();
        } else {
          this.nav.style.display = 'none';
        }
        break;
      case 'auto':
        this.autoplay(value);
        break;
    }
  }

  Swipe.prototype.attempSlide = function(delta) {
    if (this.sliding) return;

    var style = this.wrap.style;
    style.webkitTransitionDuration = '0ms';
    var offset = this.offset + delta.x;
    style.webkitTransform = 'translate3D(' + offset + 'px, 0px, 0px)';
  }

  Swipe.prototype.cancelSlide = function() {
    var style = this.wrap.style;
    style.webkitTransitionDuration = this.speed + 'ms';
    style.webkitTransform = 'translate3D(' + this.offset + 'px, 0px, 0px)';
  }

  Swipe.prototype.createNav = function() {
    this.nav = document.createElement('div');
    this.nav.className = this.classes.nav;
    for (var i = 0; i < this.length; i++) {
      var navItem = document.createElement('span');
      navItem.className = this.classes.navItem;
      this.nav.appendChild(navItem);
    }
    this.container.appendChild(this.nav);
  }

  Swipe.prototype.setNav = function() {
    for (var i = 0; i < this.length; i++) {
      this.nav.children[i].classList.remove(this.classes.navOn);
    }
    this.nav.children[this.index].classList.add(this.classes.navOn);
  }

  Swipe.getLength = function() {
    return this.length;
  }

  Swipe.prototype.autoplay = function(onOff) {
    if (this.auto == 0) return;

    clearInterval(this.timer);
    var that = this;
    if (onOff) {
      this.timer = setInterval(function() {
        that.next();
      }, this.auto);
    }
  }

  Swipe.prototype.kill = function() {
    this.container.removeChild(this.nav);
    this.container.removeEventListener('transitionend', this.events);
    this.container.removeEventListener('touchstart', this.events);
  }

  Swipe.v = Swipe.version = '1.0.0';
  return Swipe;
})


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。