JS实现滑动插件


Posted in Javascript onJanuary 15, 2020

本文实例为大家分享了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);
}

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

Javascript 相关文章推荐
JS获取scrollHeight问题想到的标准问题
May 27 Javascript
番茄的表单验证类代码修改版
Jul 18 Javascript
javascript ie6兼容position:fixed实现思路
Apr 01 Javascript
js基于面向对象实现网页TAB选项卡菜单效果代码
Sep 09 Javascript
详解JavaScript函数对象
Nov 15 Javascript
星期几的不同脚本写法(推荐)
Jun 01 Javascript
js修改onclick动作的四种方法(推荐)
Aug 18 Javascript
js仿微博动态栏功能
Feb 22 Javascript
原生JS改变透明度实现轮播效果
Mar 24 Javascript
vue-resource + json-server模拟数据的方法
Nov 02 Javascript
Vue下滚动到页面底部无限加载数据的示例代码
Apr 22 Javascript
vue data变量相互赋值后被实时同步的解决步骤
Aug 05 Javascript
JS实现滑动导航效果
Jan 14 #Javascript
解决 window.onload 被覆盖的问题方法
Jan 14 #Javascript
vue quill editor 使用富文本添加上传音频功能
Jan 14 #Javascript
JavaScript事件冒泡机制原理实例解析
Jan 14 #Javascript
JS window对象简单操作完整示例
Jan 14 #Javascript
让mocha支持ES6模块的方法实现
Jan 14 #Javascript
JavaScript遍历数组的方法代码实例
Jan 14 #Javascript
You might like
在PHP的图形函数中显示汉字
2006/10/09 PHP
php通过exif_read_data函数获取图片的exif信息
2015/05/21 PHP
PHP is_array() 检测变量是否是数组的实现方法
2016/06/13 PHP
Swoole 5将移除自动添加Event::wait()特性详解
2019/07/10 PHP
Laravel 将数据表的数据导出,并生成seeds种子文件的方法
2019/10/09 PHP
jQuery随便控制任意div隐藏的方法
2013/06/28 Javascript
jquery()函数的三种语法介绍
2013/10/09 Javascript
Js冒泡事件详解及阻止示例
2014/03/21 Javascript
Javascript基础教程之数据类型转换
2015/01/18 Javascript
jquery通过扩展select控件实现支持enter或focus选择的方法
2015/11/19 Javascript
原生JS轮播图插件
2017/02/09 Javascript
不使用 JS 匿名函数理由
2017/11/17 Javascript
vue中添加mp3音频文件的方法
2018/03/02 Javascript
jquery图片预览插件实现方法详解
2019/07/18 jQuery
JSX在render函数中的应用详解
2019/09/04 Javascript
详解使用mocha对webpack打包的项目进行&quot;冒烟测试&quot;的大致流程
2020/04/27 Javascript
antd design table更改某行数据的样式操作
2020/10/31 Javascript
学习python的几条建议分享
2013/02/10 Python
Python使用re模块实现信息筛选的方法
2018/04/29 Python
Python脚本修改阿里云的访问控制列表的方法
2019/03/08 Python
python里运用私有属性和方法总结
2019/07/08 Python
python使用itchat模块给心爱的人每天发天气预报
2019/11/25 Python
简单了解pytest测试框架setup和tearDown
2020/04/14 Python
Python3如何使用tabulate打印数据
2020/09/25 Python
canvas 如何绘制线段的实现方法
2018/07/12 HTML / CSS
Timberland美国官网:全球领先的户外品牌
2016/08/15 全球购物
英文商务邀请信
2014/01/22 职场文书
公益广告语集锦
2014/03/13 职场文书
双创工作实施方案
2014/03/26 职场文书
竞选班干部演讲稿300字
2014/08/20 职场文书
端午节活动总结
2014/08/26 职场文书
关于教师节的演讲稿
2014/09/04 职场文书
领导班子民主生活会整改措施(工商局)
2014/09/21 职场文书
严以用权学习心得体会
2016/01/12 职场文书
教你用Java Swing实现自助取款机系统
2021/06/11 Java/Android
MySQL约束超详解
2021/09/04 MySQL