首頁 > web前端 > js教程 > 主體

js如何實作滑動插件

王林
發布: 2020-03-23 09:41:21
轉載
2242 人瀏覽過

js如何實作滑動插件

基本想法是封裝一個Slider類, 擁有預設初始設定參數。

Slider.prototype(原型鏈上)擁有實現滑動的方法,透過監聽手勢,實現滑動的效果。

比較複雜的滑動效果, 可以使用Swiper.js 來實現。

(推薦教學:javascript教學

程式碼如下:

/* 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 === &#39;&#39;) return style
  return vendor + style.charAt(0).toUpperCase() + style.substr(1)
}

var TRANSFORM = prefix(&#39;transform&#39;),
  TRANSITION = prefix(&#39;transition&#39;)

var Slider = function(options) {
  // 初始化配置参数
  this.options = $.extend({
    slideWrap: &#39;.pages&#39;,  // 容器
    slideItem: &#39;.page&#39;, // 滑动单元的元素
    direction: &#39;Y&#39;, // 滑动的方向
    effect: &#39;slide&#39;,  // 滑动的效果
    triggleDist: 100,  // 触发滑动的手指移动最小位移
    followFinger: true, // 是否跟随手指移动
    duration: .4,  // 翻页的延时
    currentIdx: 0  // 初始显示的页码
  }, options)

  var EffectDict = {
    &#39;slide&#39; : [&#39;slide&#39;, &#39;slide&#39;],
    &#39;scale&#39; : [&#39;slide&#39;, &#39;scale&#39;]
  }

  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 = &#39;ontouchend&#39; 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 == &#39;Y&#39; ? height : width)

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

  _bindEvents: function() {
    var _this = this,
      pagesWrap = this.pagesWrap

    var events = this._supportTouch ? &#39;touchstart touchmove touchend touchcancel&#39; : &#39;mousedown mousemove mouseup mousecancel&#39;

    events.split(&#39; &#39;).forEach(function(e) {
      pagesWrap.addEventListener(e, _this)
    })

    window.addEventListener(&#39;orientationchange&#39;, this)
    window.addEventListener(&#39;resize&#39;, this)
  },

  handleEvent: function(e) {
    switch (e.type) {
      case &#39;orientationchange&#39;:
      case &#39;resize&#39;:
        this._init()
        break
      case &#39;touchstart&#39;:
      case &#39;mousedown&#39;:
        this._start(e)
        break
      case &#39;touchmove&#39;:
      case &#39;mousemove&#39;:
        this._move(e)
        break
      case &#39;touchend&#39;:
      case &#39;touchcancel&#39;:
      case &#39;mouseup&#39;:
      case &#39;mousecancel&#39;:
        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],
      $next = $current.nextElementSibling,
      $prev = $current.previousElementSibling,
      xDist = touches.pageX - this._pageX,
      yDist = touches.pageY - this._pageY,
      enter = this._enter,
      leave = this._leave,
      moveDist = this._moveDist = (direction == &#39;X&#39; ? 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,
      distance = this._distance,
      triggleDist = this.options.triggleDist,
      enter = this._enter,
      $current = this.pages[this.options.currentIdx],
      $next = $current.nextElementSibling,
      $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],
      enter = this._enter,
      leave = this._leave,
      distance = (idx < this.options.currentIdx ? this._distance : -this._distance)

    $($target).one(&#39;webkitTransitionEnd&#39;, function() {
      $current.classList.remove(&#39;current&#39;)
      $target.classList.add(&#39;current&#39;)
      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) ? &#39;all 0.4s&#39; : &#39;&#39;
    el.style[TRANSFORM] = &#39;translate3d(&#39; + (&#39;Y&#39; == this.options.direction ? &#39;0, &#39; + val + &#39;px&#39; : (val + &#39;px, 0&#39;)) + &#39;,0)&#39;
  },

  scale: function(el, val) {
    el.style.webkitTransition = &#39;all 0.4s&#39;
    el.style[TRANSFORM] = &#39;scale(&#39; + (1 - Math.round(Math.abs(val) / this._distance / 4*100) / 100) + &#39;) translateZ(0)&#39;
  }
}

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);
}
登入後複製

更多酷炫javascript特效程式碼,盡在:javascript特效

以上是js如何實作滑動插件的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
js
來源:jb51.net
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
最新問題
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板