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 相关文章推荐
仿校内登陆框,精美,给那些很厉害但是没有设计天才的程序员
Nov 24 Javascript
HTML代码中标签的全部属性 中文注释说明
Mar 26 Javascript
jQuery 操作下拉列表框实现代码
Feb 22 Javascript
基于jQuery判断两个元素是否有重叠部分的代码
Jul 25 Javascript
第七篇Bootstrap表单布局实例代码详解(三种表单布局)
Jun 21 Javascript
jquery过滤特殊字符',防sql注入的实现方法
Aug 17 Javascript
jquery easyUI中ajax异步校验用户名
Aug 19 Javascript
Javascript 高性能之递归,迭代,查表法详解及实例
Jan 08 Javascript
JS中input表单隐藏域及其使用方法
Feb 13 Javascript
浅谈ES6 模板字符串的具体使用方法
Nov 07 Javascript
p5.js入门教程之键盘交互
Mar 19 Javascript
javascript实现函数柯里化与反柯里化过程解析
Oct 08 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
神族 PROTOSS 概述
2020/03/14 星际争霸
php制作文本式留言板
2015/03/18 PHP
Laravel学习教程之本地化模块
2017/08/18 PHP
Jquery+JSon 无刷新分页实现代码
2010/04/01 Javascript
js 上传图片预览问题
2010/12/06 Javascript
基于jQuery的动态增删改查表格信息,可左键/右键提示(原创自Zjmainstay)
2012/07/31 Javascript
jquery配合css简单实现返回顶部效果
2013/09/30 Javascript
IE8下String的Trim()方法失效的解决方法
2013/11/08 Javascript
Egret引擎开发指南之编译项目
2014/09/03 Javascript
JavaScript实现列表分页功能特效
2015/05/15 Javascript
轻松实现javascript图片轮播特效
2016/01/13 Javascript
JavaScript从0开始构思表情插件
2016/07/26 Javascript
浅谈JavaScript中变量和函数声明的提升
2016/08/09 Javascript
JavaScript数据类型学习笔记分享
2016/09/01 Javascript
Bootstrap基本样式学习笔记之图片(6)
2016/12/07 Javascript
JS中的数组转变成JSON格式字符串的方法
2017/05/09 Javascript
使用Vue构建可重用的分页组件
2018/03/26 Javascript
three.js搭建室内场景教程
2018/12/30 Javascript
JS实现简易图片自动轮播
2020/10/16 Javascript
JavaScript 防盗链的原理以及破解方法
2020/12/29 Javascript
Ubuntu 14.04+Django 1.7.1+Nginx+uwsgi部署教程
2014/11/18 Python
python简单实现计算过期时间的方法
2015/06/09 Python
Python实现将数据库一键导出为Excel表格的实例
2016/12/30 Python
Python实现的双色球生成功能示例
2017/12/18 Python
python面向对象法实现图书管理系统
2019/04/19 Python
用django设置session过期时间的方法解析
2019/08/05 Python
Flask和pyecharts实现动态数据可视化
2020/02/26 Python
python实现电子词典
2020/03/03 Python
Python3.8.2安装包及安装教程图文详解(附安装包)
2020/11/28 Python
美国内衣品牌:Leonisa
2016/08/14 全球购物
荷兰多品牌网上鞋店:Stoute Schoenen
2017/08/24 全球购物
管理学专业个人求职信范文
2013/12/13 职场文书
初中政治教学反思
2014/01/17 职场文书
校本培训个人总结
2015/02/28 职场文书
检讨书模板大全
2015/05/07 职场文书
入党团支部推荐意见
2015/06/02 职场文书