使用原生js封装webapp滑动效果(惯性滑动、滑动回弹)


Posted in Javascript onMay 06, 2014

PC 移动端兼容  IE 6.0+, FF 1.5+, Safari 2.0+, Opera 9.0+ 惯性助动,滑动回弹

门面模式

window.onload = function() {
 /*测试数据*/
 var insert = '';
 for (var i = 0; i < 80; i++) {
  insert += '<div style = "width:100%; text-align:center;">滑动测试 ' + i + '</div>';
 }
 document.getElementById("moveArea").innerHTML = insert;
 /*测试数据   */
 var at = new appTouch({
  tContain : 'appArea', //必选:滑动区域id
  tMove : 'moveArea', //必选:移动区域id
  tScroller : 'scroller', //必选:自定义滚动条
  tScrollerArea : 'scrollerArea'//必选:滚动条区域
 }, onmoveend);
 //到顶/底回调
 function onmoveend(m) {
  //console.log(m);
 }
}
/*=====================
 * 名称: appTouch
 * 功能: web app滑动模拟组件
 * 参数: 相关配置
 ======================*/
var appTouch = function(config, callback) {
 this.touchContain = config.tContain;
 this.touchMove = config.tMove;
 this.touchScroller = config.tScroller;
 this.touchScrollerArea = config.tScrollerArea;
 this.callbackfn = callback;
 this.move();
}
appTouch.prototype = {
 move : function(e) {
  var monitor = document.getElementById(this.touchContain), //监听容器
  target = document.getElementById(this.touchMove), //移动目标
  scroller = document.getElementById(this.touchScroller), //自定义滚动条
  scrollerArea = document.getElementById(this.touchScrollerArea), //滚动条区域
  sheight = monitor.offsetHeight / target.offsetHeight * monitor.offsetHeight, //自定义滚动条的长度
  st = (target.offsetHeight - monitor.offsetHeight) / (monitor.offsetHeight - sheight), //移动块对应滚轮单位长度
  tslow = 4, //到顶/底减基数
  tMove = 0, //滑块到顶top值
  tMoveL = tMove + 140, //到顶允许下拉范围
  bMove = monitor.offsetHeight - target.offsetHeight, //滑块到底top值
  bMoveL = bMove - 140, //到底允许上滑范围
  callbackfn = this.callbackfn, //回调函数
  flg = false, //标记是否滑动
  startY, //标记起始位置
  startTop, //标记滑动起始时的高度值
  move = 0;
  //移动距离
  //鼠标事件注册
  addEvent(monitor, 'mousedown', moveStart);
  addEvent(monitor, 'mousemove', moveIn);
  addEvent(monitor, 'mouseup', moveEnd);
  addEvent(window, 'mousemove', moveIn);
  addEvent(window, 'mouseup', moveEnd);
  //移动设备触摸事件注册
  addEvent(monitor, 'touchstart', moveStart);
  addEvent(monitor, 'touchmove', moveIn);
  addEvent(monitor, 'touchend', moveEnd);
  /**
   *外观/门面模式包装
   */
  /*事件监听 */
  function addEvent(el, type, fn) {
   if (el.addEventListener) {
    el.addEventListener(type, fn, false);
   } else if (el.attachEvent) {
    el.attachEvent('on' + type, fn);
   } else {
    el['on' + type] = fn;
   }
  }
  //取消浏览器默认行为
  function stop(e) {
   //Opera/Chrome/FF
   if (e.preventDefault)
    e.preventDefault();
   //IE
   e.returnValue = false;
  }
  //包装结束
  /**
   *操作函数
   */
  //惯性缓动参数
  var lastMoveTime = 0;
  var lastMoveStart = 0;
  var stopInertiaMove = false;
  /*移动触发*/
  function moveStart(e) {
   stop(e);
   flg = true;
   if (e.touches)
    e = e.touches[0];
   startY = e.clientY;
   startTop = target.style.top || 0;
   //惯性缓动
   lastMoveStart = startY;
   lastMoveTime = new Date().getTime();
   stopInertiaMove = true;
   scrollerArea.style.visibility = 'visible';
  }
  /*移动过程中*/
  function moveIn(e) {
   if (flg) {
    stop(e);
    if (e.touches)
     e = e.touches[0];
    move = e.clientY - startY + parseInt(startTop);
    if (move > tMove) {
     (move - tMove) / tslow + tMove > tMoveL ? move = tMoveL : move = (move - tMove) / tslow + tMove
    } else if (move < bMove)
     (move - bMove) / tslow + bMove < bMoveL ? move = bMoveL : move = (move - bMove) / tslow + bMove;
    target.style.top = move + 'px';
    scroller.style.top = -move / st + 'px';
    //惯性缓动
    var nowTime = new Date().getTime();
    stopInertiaMove = true;
    if (nowTime - lastMoveTime > 300) {
     lastMoveTime = nowTime;
     lastMoveStart = e.clientY;
    }
   }
  }
  /*移动结束*/
  function moveEnd(e) {
   stop(e);
   if (e.touches)
    e = e.touches[0];
   //惯性缓动
   var contentTop = target.style.top.replace('px', '');
   var contentY = (parseInt(contentTop) + e.clientY - lastMoveStart);
   var nowTime = new Date().getTime();
   var v = (e.clientY - lastMoveStart) / (nowTime - lastMoveTime);
   //最后一段时间手指划动速度
   stopInertiaMove = false;
   (function(v, startTime, contentY) {
    var dir = v > 0 ? -1 : 1;
    //加速度方向
    var deceleration = dir * 0.005;
    function inertiaMove() {
     if (stopInertiaMove)
      return;
     var nowTime = new Date().getTime();
     var t = nowTime - startTime;
     var nowV = v + t * deceleration;
     var moveY = (v + nowV) / 2 * t;
     // 速度方向变化表示速度达到0了
     if (dir * nowV > 0) {
      if (move > tMove) {
       callbackfn('到顶了');
       target.style.top = tMove + 'px';
       scroller.style.top = tMove + 'px';
      } else if (move < bMove) {
       callbackfn('到底了');
       target.style.top = bMove + 'px';
       scroller.style.top = -bMove / st + 'px';
      }
      setTimeout(function() {
       if (!stopInertiaMove)
        scrollerArea.style.visibility = 'hidden';
      }, 4000);
      return;
     }
     move = contentY + moveY;
     if (move > tMove) {
      t /= 20;
      move = (move - tMove) / 10 + tMove;
     } else if (move < bMove) {
      t /= 20;
      move = (move - bMove) / 10 + bMove;
     }
     target.style.top = move + "px";
     scroller.style.top = -move / st + 'px';
     setTimeout(inertiaMove, 10);
    }
    inertiaMove();
   })(v, nowTime, contentY);
   move = 0;
   flg = false;
  }
  //操作结束
  /**
   *相关初始化
   */
  //滚动条长度初始化
  scroller.style.height = sheight + 'px';
  //初始化结束
 },
 otherInteract : function() {
  //其他功能扩充
 }
}

IE hack css

body,html {background-color:#333; margin: 0; height: 100%; line-height: 2.0; font-family: 'Microsoft YaHei'; overflow-y:hidden;}
#contain{margin: 0 auto; position:relative; width: 100%; max-width: 480px; _width: 480px; height: 100%; cursor: pointer !important;}
#appArea{position: absolute; width: 100%; height: 100%; overflow: hidden;  background-color: #fff;}  
#topInfo{position: absolute;top: 60px;width: 100%; height:60px; text-align: center; font-size: 18px; }
#bottomInfo{position: absolute;bottom: 0;width: 100%;}
#scrollerArea{position: absolute; right: 0; width: 1.5%; height: 100%;visibility: hidden;}
#scroller{position: absolute; top:0; width: 100%;  background-color: #aaa;}
#moveArea{position: absolute; top:0px; width: 100%; background-color: #ddd;}

HTML代码

<!DOCTYPE html>
<html>
 <head>
  <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0,user-scalable=no">
  <link type="text/css" href="css/main.css" rel="stylesheet">
  <title>滑动回弹</title>
  <!--[if lt IE 9]>      <![endif]-->
  <noscript></noscript>
 </head>
 <body>
  <div id="contain">
   <div id="appArea">
    <div id="topInfo">
     logo or animate
    </div>
    <div id="bottomInfo">
     some imformation  2014-4-28
    </div>
    <div id="moveArea"></div>
    <div id="scrollerArea">
     <div id="scroller"></div>
    </div>
   </div>
  </div>
  <script src="js/main.js"></script>
 </body>
</html>
Javascript 相关文章推荐
firefo xml 读写实现js代码
Jun 11 Javascript
网页中的图片的处理方法与代码
Nov 26 Javascript
Jquery 获取checkbox的checked问题
Nov 16 Javascript
Javascript图像处理—虚拟边缘介绍及使用方法
Dec 27 Javascript
如何实现修改密码时密码框显示保存到cookie的密码
Dec 10 Javascript
js中substring和substr的定义和用法
May 05 Javascript
详解jquery validate实现表单验证 (正则表达式)
Jan 18 Javascript
Vue2.0表单校验组件vee-validate的使用详解
May 02 Javascript
vue.js整合mint-ui里的轮播图实例代码
Dec 27 Javascript
p5.js实现斐波那契螺旋的示例代码
Mar 22 Javascript
Vue2.0 实现单选互斥的方法
Apr 13 Javascript
详解基于Vue cli生成的Vue项目的webpack4升级
Jun 19 Javascript
一些老手都不一定知道的JavaScript技巧
May 06 #Javascript
jQuery中的$.ajax()方法应用
May 06 #Javascript
jquery判断元素是否隐藏的多种方法
May 06 #Javascript
JQuery调用WebServices的方法和4个实例
May 06 #Javascript
通过JQuery将DIV的滚动条滚动到指定的位置方便自动定位
May 05 #Javascript
JQuery以JSON方式提交数据到服务端示例代码
May 05 #Javascript
使用jQuery重置(reset)表单的方法
May 05 #Javascript
You might like
用php来改写404错误页让你的页面更友好
2013/01/24 PHP
php登陆页的密码处理方式分享
2013/10/14 PHP
输入值/表单提交参数过滤有效防止sql注入的方法
2013/12/25 PHP
php返回字符串中所有单词的方法
2015/03/09 PHP
PHP5多态性与动态绑定介绍
2015/04/03 PHP
Zend Framework教程之Zend_Config_Xml用法分析
2016/03/23 PHP
yii2缓存Caching基本用法示例
2016/07/18 PHP
PHP上传图片、删除图片简单实例
2016/11/12 PHP
Thinkphp5 微信公众号token验证不成功的原因及解决方法
2017/11/12 PHP
Gambit vs CL BO3 第一场 2.13
2021/03/10 DOTA
基于jQuery的淡入淡出可自动切换的幻灯插件
2010/08/24 Javascript
hover的用法及live的用法介绍(鼠标悬停效果)
2013/03/29 Javascript
ie下$.getJSON出现问题的解决方法
2014/02/12 Javascript
JS+CSS实现大气的黑色首页导航菜单效果代码
2015/09/10 Javascript
关于事件mouseover ,mouseout ,mouseenter,mouseleave的区别
2015/10/12 Javascript
谈谈我对JavaScript原型和闭包系列理解(随手笔记9)
2015/12/24 Javascript
Angular中$compile源码分析
2016/01/28 Javascript
基于Bootstrap框架实现图片切换
2017/03/10 Javascript
如何重置vue打印变量的显示方式
2017/12/06 Javascript
Angular实现的内置过滤器orderBy排序与模糊查询功能示例
2017/12/29 Javascript
angular 实现的输入框数字千分位及保留几位小数点功能示例
2018/06/19 Javascript
vue-cli V3.0版本的使用详解
2018/10/24 Javascript
node.js的Express服务器基本使用教程
2019/01/09 Javascript
微信小程序获取用户信息的两种方法wx.getUserInfo与open-data实例分析
2019/05/03 Javascript
Electron vue的使用教程图文详解
2019/07/05 Javascript
Python使用matplotlib绘制随机漫步图
2018/08/27 Python
python使用ctypes调用扩展模块的实例方法
2020/01/28 Python
HTML5学习笔记之html5与传统html区别
2016/01/06 HTML / CSS
深入浅析HTML5中的article和section的区别
2018/05/15 HTML / CSS
骨干教师培训制度
2014/01/13 职场文书
人力资源部经理助理岗位职责
2014/03/04 职场文书
商超业务员岗位职责
2014/03/12 职场文书
格列佛游记读书笔记
2015/06/30 职场文书
中学图书馆工作总结
2015/08/11 职场文书
感恩教育主题班会
2015/08/12 职场文书
在 Python 中利用 Pool 进行多线程
2022/04/24 Python