1. 程式人生 > 程式設計 >JS實現滑動外掛

JS實現滑動外掛

本文例項為大家分享了JS實現滑動外掛的具體程式碼,供大家參考,具體內容如下

基本思路是封裝一個Slider類, 擁有預設初始配置引數。
Slider.prototype(原型鏈上)擁有實現滑動的方法,通過監聽手勢,實現滑動的效果。
比較複雜的滑動效果, 可以使用Swiper.js 來實現。

/* PollyFill for iOS 5.* */
if (!Function.prototype.bind) {
  Function.prototype.bind = function (oThis) {
    var args = Array.prototype.slice.call(arguments,1)
    var f2bind = this
    var fnop = function () {}
    var bound = function () {
      return f2bind.apply(this instanceof fnop && oThis
        ? this
        : oThis,args.concat(Array.prototype.slice.call(arguments)))
    }
    fnop.prototype = this.prototype
    bound.prototype = new fnop()
    return bound
  }
}

// 新增瀏覽器字首
function prefix(style) {
  var vendor = (function() {
    var transArr = ['transform','webkitTransform','MozTransform','msTranform','OTransform'],vendors = ['','webkit','Moz','ms','O'],elementStyle = document.createElement('div').style

    for (var i = 0; i < vendors.length; i++) {
      if (transArr[i] in elementStyle) {
        return vendors[i]
      }
    }

    return false
  })()

  if (vendor === false) return false
  if (vendor === '') return style
  return vendor + style.charAt(0).toUpperCase() + style.substr(1)
}

var TRANSFORM = prefix('transform'),TRANSITION = prefix('transition')

var Slider = function(options) {
  // 初始化配置引數
  this.options = $.extend({
    slideWrap: '.pages',// 容器
    slideItem: '.page',// 滑動單元的元素
    direction: 'Y',// 滑動的方向
    effect: 'slide',// 滑動的效果
    triggleDist: 100,// 觸發滑動的手指移動最小位移
    followFinger: true,// 是否跟隨手指移動
    duration: .4,// 翻頁的延時
    currentIdx: 0  // 初始顯示的頁碼
  },options)

  var EffectDict = {
    'slide' : ['slide','slide'],'scale' : ['slide','scale']
  }

  this.pagesWrap = document.querySelector(this.options.slideWrap)
  this.pages = document.querySelectorAll(this.options.slideItem)

  this.hook = this.options.slideController
  this._total = this.pages.length
  this._pageX = 0
  this._pageY = 0
  this._distance = 0 // 頁面之間切換的距離
  this._moveDist = 0 // touch 滑動的距離
  this._supportTouch = 'ontouchend' in window
  this._touching = false

  this._enter = this[EffectDict[this.options.effect][0]].bind(this)
  this._leave = this[EffectDict[this.options.effect][1]].bind(this)

  this._init()
  this._bindEvents()
}
Slider.prototype = {
  _init: function() {
    var width = this.pagesWrap.clientWidth,height = this.pagesWrap.clientHeight,currentIdx = this.options.currentIdx,pages = this.pages,total = this._total,distance = this._distance = (this.options.direction == 'Y' ? height : width)

    // 初始化各個 page 的位置
    for (var i = 0; i < this._total; i++) {
      if (i == currentIdx) {
        pages[i].classList.add('current')
      } else {
        this._enter(pages[i],i < currentIdx ? -distance : distance,2)
      }
    }
  },_bindEvents: function() {
    var _this = this,pagesWrap = this.pagesWrap

    var events = this._supportTouch ? 'touchstart touchmove touchend touchcancel' : 'mousedown mousemove mouseup mousecancel'

    events.split(' ').forEach(function(e) {
      pagesWrap.addEventListener(e,_this)
    })

    window.addEventListener('orientationchange',this)
    window.addEventListener('resize',this)
  },handleEvent: function(e) {
    switch (e.type) {
      case 'orientationchange':
      case 'resize':
        this._init()
        break
      case 'touchstart':
      case 'mousedown':
        this._start(e)
        break
      case 'touchmove':
      case 'mousemove':
        this._move(e)
        break
      case 'touchend':
      case 'touchcancel':
      case 'mouseup':
      case 'mousecancel':
        this._end(e)
        break
    }
  },_start: function(e) {
    if (this._touching) {
      e.preventDefault()
      e.stopPropagation()
      return
    }

    this._touching = true
    this._moveDist = 0

    var touches = (this._supportTouch ? e.touches[0] : e),distance = this._distance,enter = this._enter

    var $current = this.pages[this.options.currentIdx],$next = $current.nextElementSibling,$prev = $current.previousElementSibling

    this._pageX = touches.pageX
    this._pageY = touches.pageY

    $current.style.zIndex = 1

    if ($next) {
      $next.style.zIndex = 2
      enter($next,distance)
    }

    if ($prev) {
      $prev.style.zIndex = 2
      enter($prev,-distance)
    }
  },_move: function(e) {
    e.preventDefault()

    if (!this._touching) return

    var touches = (this._supportTouch ? e.touches[0] : e),direction = this.options.direction,distance = this._distance

    var currentIdx = this.options.currentIdx,$current = this.pages[this.options.currentIdx],$prev = $current.previousElementSibling,xDist = touches.pageX - this._pageX,yDist = touches.pageY - this._pageY,enter = this._enter,leave = this._leave,moveDist = this._moveDist = (direction == 'X' ? xDist : yDist)

    if (this.options.followFinger) {
      $next && enter($next,moveDist + distance)
      $prev && enter($prev,moveDist - distance)

      // 因為不能翻頁,所以製造拖動困難的效果
      if ((currentIdx == 0 && moveDist > 0) || (currentIdx == this._total && moveDist < 0)) {
        return this.slide($current,moveDist / 4)
      }

      leave($current,moveDist)
    }
  },_end: function(e) {
    var move = this._moveDist,triggleDist = this.options.triggleDist,$prev = $current.previousElementSibling

    this._touching = false

    this._enter($current,0)
    $next && enter($next,distance)
    $prev && enter($prev,-distance)

    if ($next && move < -triggleDist && this.hook.shouldGoToNext($current)) return this._next()
    if ($prev && move > triggleDist && this.hook.shouldGoToPrev($current)) return this._prev()
  },_next: function() {
    this.go2page(this.options.currentIdx + 1)
  },_prev: function() {
    this.go2page(this.options.currentIdx - 1)
  },go2page: function(idx) {

    var $current = this.pages[this.options.currentIdx],$target = this.pages[idx],distance = (idx < this.options.currentIdx ? this._distance : -this._distance)

    $($target).one('webkitTransitionEnd',function() {
      $current.classList.remove('current')
      $target.classList.add('current')
      this.hook.didGoToPage($target,$current)
    }.bind(this))

    leave($current,distance)
    enter($target,0)

    this._moveDist = 0
    this.options.currentIdx = idx
  },/**
   * 切頁的效果
   * 目前只支援兩種效果:
   * 1. Slide(普通的滑動)
   * 2. Scale(縮放滑動)
   */
  slide: function(el,val,need) {
    need = need || 1
    el.style.webkitTransition = (need == 1) ? 'all 0.4s' : ''
    el.style[TRANSFORM] = 'translate3d(' + ('Y' == this.options.direction ? '0,' + val + 'px' : (val + 'px,0')) + ',0)'
  },scale: function(el,val) {
    el.style.webkitTransition = 'all 0.4s'
    el.style[TRANSFORM] = 'scale(' + (1 - Math.round(Math.abs(val) / this._distance / 4*100) / 100) + ') translateZ(0)'
  }
}

var slideController = {
  shouldGoToPrev: function(el) {
    return false;
  },shouldGoToNext: function(el) {
    return false;;
  },didGoToPage: function(el,prevEl) {
    return false;
  }
}


function query(selector){
  return document.querySelector(selector);
}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。