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 相关文章推荐
JavaScript实现动态增加文件域表单
Feb 12 Javascript
javascript 匿名函数的理解(透彻版)
Jan 28 Javascript
一个关于javascript匿名函数的问题分析
Mar 30 Javascript
SOSO地图JS画出标注和中心点以html形式运行
Aug 09 Javascript
showModalDialog模态对话框的使用详解以及浏览器兼容
Jan 11 Javascript
关闭浏览器输入框自动补齐 兼容IE,FF,Chrome等主流浏览器
Feb 11 Javascript
微信小程序-拍照或选择图片并上传文件
Jan 06 Javascript
基于Vue组件化的日期联动选择器功能的实现代码
Nov 30 Javascript
使用VScode 插件debugger for chrome 调试react源码的方法
Sep 13 Javascript
TypeScript之调用栈的实现
Dec 31 Javascript
微信小程序修改checkbox的样式代码实例
Jan 21 Javascript
Vue + ts实现轮播插件的示例
Nov 10 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实现邮件群发的源码
2013/06/18 PHP
php实现将字符串按照指定距离进行分割的方法
2015/03/14 PHP
php多重接口的实现方法
2015/06/20 PHP
php字符串的替换,分割和连接方法
2016/05/23 PHP
thinkphp5使html5实现动态跳转的例子
2019/10/16 PHP
使用Git实现Laravel项目的自动化部署
2019/11/24 PHP
js 操作css实现代码
2009/06/11 Javascript
JavaScript中的类继承
2010/11/25 Javascript
JavaScript实现页面跳转的方式汇总
2016/05/16 Javascript
微信小程序 图片宽度自适应的实现
2017/04/06 Javascript
AngularJS页面带参跳转及参数解析操作示例
2017/06/28 Javascript
利用types增强vscode中js代码提示功能详解
2017/07/07 Javascript
Django+Vue.js搭建前后端分离项目的示例
2017/08/07 Javascript
nodejs超出最大的调用栈错误问题
2017/12/27 NodeJs
js代码实现轮播图
2020/05/04 Javascript
Jquery Fade用法详解
2020/11/06 jQuery
通过数据库对Django进行删除字段和删除模型的操作
2015/07/21 Python
Python深入06——python的内存管理详解
2016/12/07 Python
Python3中的bytes和str类型详解
2019/05/02 Python
Python搭建Spark分布式集群环境
2019/07/05 Python
利用python-docx模块写批量生日邀请函
2019/08/26 Python
Python3之字节串bytes与字节数组bytearray的使用详解
2019/08/27 Python
用Python解数独的方法示例
2019/10/24 Python
pygame实现五子棋游戏
2019/10/29 Python
基于python调用psutil模块过程解析
2019/12/20 Python
Lookfantastic意大利官网:英国知名美妆购物网站
2019/05/31 全球购物
亚洲颇具影响力的男性在线购物零售商:His
2019/11/24 全球购物
如何写毕业求职自荐信
2013/11/06 职场文书
新员工欢迎词
2014/01/12 职场文书
2014政务公开实施方案
2014/02/19 职场文书
入学申请自荐信范文
2014/02/26 职场文书
文化与传播毕业生求职信
2014/03/09 职场文书
2014年巴西世界杯口号
2014/06/05 职场文书
暑期培训班策划方案
2014/08/26 职场文书
婚内房产协议书范本
2014/10/02 职场文书
GoFrame基于性能测试得知grpool使用场景
2022/06/21 Golang