欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

JS实现滑动插件

程序员文章站 2022-06-22 14:23:03
本文实例为大家分享了js实现滑动插件的具体代码,供大家参考,具体内容如下 基本思路是封装一个slider类, 拥有默认初始配置参数。 slider.prototype(原型链...

本文实例为大家分享了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],
      $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 == '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,
      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('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);
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。