目录
2. 基本结构
5. 限制滑动区间
6. 设定反弹区间
7. 完整代码
首页 web前端 js教程 原生js实现移动端Touch滑动反弹的方法(代码示例)

原生js实现移动端Touch滑动反弹的方法(代码示例)

Jan 11, 2019 am 10:42 AM
css html5 javascript

本篇文章给大家带来的内容是关于原生js实现移动端Touch滑动反弹的方法(代码示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

移动端 Touch 滑动反弹

什么是Touch滑动?就是类似于PC端的滚动事件,但是在移动端是没有滚动事件的,所以就要用到Touch事件结合js去实现,效果如下:

49134015-5c37ff2e33c57_articlex.gif

1. 准备工作

什么是移动端的Touch事件?在移动端Touch事件可以细分成三种,分别是:touchstart、touchmove和touchend,并且touch事件必须要用addEventListener去监听。

touchStart当手指触碰到屏幕的时候触发

touchmove当手指在屏幕上不断移动的时候触发

touchend当手指离开屏幕的时候触发

Touch 事件触发的 Event 对象:

// 手指触碰到屏幕时触发
element.addEventListener('touchstart', function (e) {
    // 打印的事件对象
    console.log(e);
})
登录后复制

3474418864-5c37ff2dc4db4_articlex.jpg

changedTouches、targetTouches、touches都是伪数组,里面装的是手指列表

三种返回对象的区别:

其实这三种返回的对象,都是表示用户触摸事件时的手指信息,之所以是一个伪数组,是因为有可能出现多指同时触摸,但是在实际工作中一般不去考虑多指的情况。而它们唯一的区别就是在touchstart和touchmove事件的时候,changedTouches、targetTouches、touches都能获取到手指的信息,但是在touchend事件的时候,targetTouches、touches对象是不能返回离开屏幕时的手指信息,只有changedTouches对象能返回。

有哪些手指信息?

我们可以看下上面的图片,在changedTouche[0]中,有些值:
clientX:74    // 触摸点相对于浏览器的 viewport 左边缘的 x 坐标,不会包括左边的滚动距离。
clientY:73    // 触摸点相对于浏览器的 viewport 上边缘的 Y 坐标,不会包括上边的滚动距离。
screenX:2202  // 触摸点相对于屏幕左边缘的 x 坐标。
screenY:327   // 触摸点相对于屏幕上边缘的 Y 坐标。
pageX:65      // 触摸点相对于 document 的左边缘的 x 坐标,包括左边的滚动距离
pageY:18      // 触摸点相对于 document 的上边缘的 Y 坐标,包括左边的滚动距离
登录后复制

2. 基本结构

此案例模拟的是移动端的一种滑动菜单效果。

HTML部分:

<aside class="main">
  <div class="draw" id="draw">
    <ul>
      <li style="background:orange">列表一</li>
      <li style="background:yellowgreen">列表二</li>
      <li style="background:yellow">列表三</li>
      <li style="background:cyan">列表四</li>
      <li style="background:orangered">列表五</li>
      <li style="background:pink">列表六</li>
      <li style="background:red">列表七</li>
      <li style="background:purple">列表八</li>
      <li style="background:violet">列表九</li>
      <li style="background:brown">列表十</li>
    </ul>
  </div>
</aside>
登录后复制

css部分:

在列表的父盒子上设定一个overflow: hidden属性,使超出盒子部分的列表暂时隐藏掉,后面会通过js去实现滑动。

/* 样式初始化 */
* {
  margin: 0;
  padding: 0;
}

html,
body {
  width: 100%;

}

aside {
  height: 100%;
  width: 100%;
}
/* 列表的父盒子,限制宽高 */
/* 注意设置overflow: hidden;样式后,超出这个盒子的ul将不会显示 */
.draw {
  width: 60px;
  height: 500px;
  border: 2px solid #ccc;
  overflow: hidden;
  position: fixed;
  left: 10px;
  top: 50%;
  transform: translateY(-50%);
}

/* li 设置了浮动, 所以 ul 要清除浮动 */
ul:after {
  content: "";
  display: block;
  visibility: hidden;
  height: 0;
  clear: both;
}

ul {
  zoom: 1;
}

li {
  list-style: none;
  float: left;
  width: 60px;
  height: 60px;
  line-height: 60px;
  text-align: center;
}
登录后复制

效果图:

943981048-5c37ff2d9680e_articlex.jpg

3. 首次滑动

手指触摸到列表向下滑动的时候,列表应该跟着向下滑动,当手指离开屏幕的时候,列表应该停在滑动的位置。这里就会用到上面准备阶段的知识点了,不明白的可以参考上面的概念。

实现原理:

1、touchstart的时候,获取手指触摸的落点A,通过这个点对象里面的clientY属性,获取距离顶部可视区的距离;

2、touchmove的时候,获取手指的点B,同样的获取移动时距离顶部可视区的距离;

3、touchmove的时候,还要做另一件事情,就是获取两点的差值(B.clientY-A.clientY),将这个差值动态赋值给ul,ul只需要设置向Y轴方向偏移这个距离,就能实现列表随手指滑动

先来张示意图,怎么通过 js 让列表滑动起来:

3840844191-5c37ff2d8f2d8_articlex.jpg

示例代码:

var draw = document.querySelector('#draw');
var ul = draw.children[0];

// touchstart 时,记录手指在 Y 轴上的落点距离可视顶部距离
var startY = 0
ul.addEventListener('touchstart', function (e) {
  startY = e.changedTouches[0].clientY;
})
// touchmove 时,记录此时手指在 Y 轴上的落点距离可视顶部距离
ul.addEventListener('touchmove', function (e) {
  // 获取差值
  var dy = e.changedTouches[0].clientY - startY;
  // 设置 ul 在 Y 轴上的偏移
  ul.style.transform = 'translateY(' + dy + 'px)';
})
登录后复制

效果图:

745534013-5c37ff2d96e73_articlex.gif

4. 再次滑动

上面的效果图,细心的朋友可能已经发现了问题,在第一次的时候,得到了我们想要的效果,但是在第二次的时候,我们继续向下移动了一段距离,但是ul并没有接着第一次的位置继续向下,而是瞬间跳了上去。

问题分析:

虽然第二次是继续向下移动了一段距离,但是触摸结束后,最终是将此时的差值,重新赋值给了ul的Y轴偏移,所以视觉上“跳了上去”。

3135543843-5c37ff2d6b7c5_articlex.jpg

解决方法:

每一次滑动结束之后,都应该记录下此次滑动的距离,与之前的进行累加,待下一次滑动的时候,ul在Y轴的偏移值应该是之前的距离加上本次滑动的距离。

新增touchend事件,在该事件里同样的可以获取到本次滑动的距离,将它与上一次的距离相加,赋值给一个全局变量;

在touchmove事件里有点小改动,就是在给ul设置偏移值的时候,除了本次滑动的差值还要加上这个上一次的值;

示意图:

3478683074-5c37ff2d79d48_articlex.jpg

示例代码:

var draw = document.querySelector('#draw');
var ul = draw.children[0];

var startY = 0 // 刚触碰到屏幕的时的手指信息
var centerY = 0 // 用来记录每次触摸时上一次的偏移距离

// touchstart 时,记录手指在 Y 轴上的落点距离可视顶部距离
ul.addEventListener('touchstart', function (e) {
  startY = e.changedTouches[0].clientY;
})

// touchmove 时,记录此时手指在 Y 轴上的落点距离可视顶部距离
ul.addEventListener('touchmove', function (e) {
  // 获取差值
  var dy = e.changedTouches[0].clientY - startY;
  // 上次的滑动距离加上本次的滑动距离
  var tempY = centerY + dy;
  // 设置 ul 在 Y 轴上的偏移
  ul.style.transform = 'translateY(' + tempY + 'px)';
})

// touchend 时,记录此时手指在 Y 轴上的落点距离可视顶部距离
ul.addEventListener('touchend', function (e) {
  // 获取差值
  var dy = e.changedTouches[0].clientY - startY;
  // 记录移动的距离
  centerY = centerY + dy;
})
登录后复制

效果图:

2653866555-5c37ff2e0c00a_articlex.gif

5. 限制滑动区间

到上面一步,我们已经可以实现列表的滑动了,但是也存在一个问题,就是向上或者向下的时候没有限制,上下可以无限的滑动,甚至再用点力,就看不到列表了。为了美观和实用,这样肯定不行的,需要给它设定一个区间,设定向上或者向下最多只能留白多少。

1320041135-5c37ff2d13429_articlex.jpg

限制向下滑动最大区间:

设定向下最大区间的值比较简单,直接设定一个值,当上一次滑动的距离加上本次滑动的距离大于这个值的时候,就不让它再继续往下滑了,让他直接等于这个设定的值。

示例代码:

var maxDown = 50; // 设定一个最大向下滑动的距离

// touchmove 时,记录此时手指在 Y 轴上的落点距离可视顶部距离
ul.addEventListener('touchmove', function (e) {
  // 获取差值
  var dy = e.changedTouches[0].clientY - startY;

  // 上次的滑动距离加上本次的滑动距离
  var tempY = centerY + dy;

  // 当上次滑动的距离加上本次滑动的距离 大于 设定的最大向下距离的时候
  if (tempY > maxDown) {
    // 直接让偏移的值 等于这个设定值
    tempY = maxDown;
  }

  // 设置 ul 在 Y 轴上的偏移
  ul.style.transform = 'translateY(' + tempY + 'px)';
})
登录后复制

限制向上滑动最大区间:

向上滑动时,当ul的底部距盒子底部的距离大于设定值的时候,不让其继续向上滑动,关键是这个值怎么去判断?

2340743329-5c37ff2ce2270_articlex.jpg

求出向上滑动最大值:

3003373871-5c37ff2ce946b_articlex.jpg

注意:因为ul是向上滑动的,所以求得的距离前面要加上一个负号(-

示例代码:

// 设定一个最大向下滑动的距离
var maxDown = 50; 
// 求得一个最大向上滑动的距离
var maxUp = -(ul.offsetHeight - draw.offsetHeight + maxDown); 

// touchmove 时,记录此时手指在 Y 轴上的落点距离可视顶部距离
ul.addEventListener('touchmove', function (e) {
  // 获取差值
  var dy = e.changedTouches[0].clientY - startY;

  // 上次的滑动距离加上本次的滑动距离
  var tempY = centerY + dy;

  // 当上次滑动的距离加上本次滑动的距离 大于 设定的最大向下距离的时候
  if (tempY > maxDown) {
    tempY = maxDown;
  }
  // 当上次滑动的距离加上本次滑动的距离 小于 设定的最大向上距离的时候 
  else if (tempY < maxUp) {
    // 直接让偏移的值 等于这个设定值
    tempY = maxUp;
  }

  // 设置 ul 在 Y 轴上的偏移
  ul.style.transform = &#39;translateY(&#39; + tempY + &#39;px)&#39;;
})
登录后复制

效果图:

1193236174-5c37ff2d8ee0c_articlex.gif

认真观察上图,虽然成功的设置了最大滑动区间,但是你有没有发现,一直往一个方向滑动的时候,虽然列表不会继续往下滑动,但是接着往相反方向滑动的时候,感觉列表滑不动,需要滑一段距离后,列表才会跟着走,这是为什么呢?因为滑动的过程centerY是一直变的,列表虽然视觉上不动了,但是在touchend事件的时候,它的centerY值一直在累加。解决方法请往下看:

6. 设定反弹区间

“滑动反弹”,这里的反弹是本篇文章的最后一步,上面说到的问题,就在这里解决。因为每一次触发touchend事件的时候,centerY值就累加一次,所以需要在touchend事件里做判断。我们设定一个反弹区间,就是当centerY的值大于或者小于某个值的时候,让它触发反弹。

设定向上反弹值:

向上的值比较简单,设置成“0”。为什么是“0”呢?我们限定只要手指离开时,上一次的滑动距离加上本次的距离> 0的时候,就让它触发反弹,并且反弹回<code>0点的位置,也就是两次滑动的距离和= 0

1329057332-5c37ff2ce6f2d_articlex.jpg

示例代码:

// 向上反弹
var maxUpBounce = 0;

// touchend 时,记录此时手指在 Y 轴上的落点距离可视顶部距离
ul.addEventListener('touchend', function (e) {
  // 获取差值
  var dy = e.changedTouches[0].clientY - startY;
  // 记录移动的距离
  centerY = centerY + dy;

  // 两次滑动的距离 大于 设定的 向上 反弹值时
  if (centerY > maxUpBounce) {
    // 让两次滑动的距离 等于 设置的值
    centerY = maxUpBounce;
    // 添加过渡
    ul.style.transition = 'transform .5s';
    ul.style.transform = 'translateY(' + centerY + 'px)';
  }
})
登录后复制

设定向下反弹值:

向下的值其实跟之前求滑动区间差不多,我们参考下图,当列表向上滑动,滑动到列表底部的时候,只要此时再向上滑动,就让它向下反弹。向下反弹值就是-(ul.offsetHeight - draw.offsetHeight),只要滑动的差值小于这个设定值,就让它向下反弹,并且反弹回设定值的位置。

2199699401-5c37ff2ce6fa4_articlex.jpg

示例代码:

// 向上反弹值
var maxUpBounce = 0; 
 // 向下反弹值
var maxDownBounce = -(ul.offsetHeight - draw.offsetHeight);

// touchend 时,记录此时手指在 Y 轴上的落点距离可视顶部距离
ul.addEventListener('touchend', function (e) {
  // 获取差值
  var dy = e.changedTouches[0].clientY - startY;
  // 记录移动的距离
  centerY = centerY + dy;

  // 两次滑动的距离 大于 设定的 向上 反弹值时
  if (centerY > maxUpBounce) {
    // 让两次滑动的距离 等于 设置的值
    centerY = maxUpBounce;
    // 添加过渡
    ul.style.transition = 'transform .5s';
    ul.style.transform = 'translateY(' + centerY + 'px)';
  }
  // 两次滑动的距离 小于 设定的 向下 反弹值时
  else if (centerY < maxDownBounce) {
    // 让两次滑动的距离 等于 设置的值
    centerY = maxDownBounce;
    // 添加过渡
    ul.style.transition = &#39;transform .5s&#39;;
    ul.style.transform = &#39;translateY(&#39; + centerY + &#39;px)&#39;;
  }
})
登录后复制

注意:touchend事件的时候,给列表添加了transition属性才会有反弹的效果,但是,下一次滑动的时候,touchmove事件的时候,这个属性还存在,所以就会出现滑动的时候有顿挫感,所以在touchmove事件的时候,一进来就清一下过渡ul.style.transition = &#39;none&#39;;

完成后效果图:

49134015-5c37ff2e33c57_articlex.gif

7. 完整代码

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>移动端 Touch 滑动反弹</title>
  <style>
    /* 样式初始化 */
    * {
      margin: 0;
      padding: 0;
    }

    html,
    body {
      width: 100%;

    }

    aside {
      height: 100%;
      width: 100%;
    }

    /* 列表的父盒子,限制宽高 */
    /* 注意设置overflow: hidden;样式后,超出这个盒子的ul将不会显示 */
    .draw {
      width: 60px;
      height: 500px;
      border: 2px solid #ccc;
      overflow: hidden;
      position: fixed;
      left: 10px;
      top: 50%;
      transform: translateY(-50%);
    }

    /* li 设置了浮动, 所以 ul 要清除浮动 */
    ul:after {
      content: "";
      display: block;
      visibility: hidden;
      height: 0;
      clear: both;
    }

    ul {
      zoom: 1;
    }

    li {
      list-style: none;
      float: left;
      width: 60px;
      height: 60px;
      line-height: 60px;
      text-align: center;
    }
  </style>
</head>
<aside>
  <div id="draw">
    <ul>
      <li style="background:orange">列表一</li>
      <li style="background:yellowgreen">列表二</li>
      <li style="background:yellow">列表三</li>
      <li style="background:cyan">列表四</li>
      <li style="background:orangered">列表五</li>
      <li style="background:pink">列表六</li>
      <li style="background:red">列表七</li>
      <li style="background:purple">列表八</li>
      <li style="background:violet">列表九</li>
      <li style="background:brown">列表十</li>
    </ul>
  </div>
</aside>

<body>
  <script>
    var draw = document.querySelector('#draw');
    var ul = draw.children[0];

    var startY = 0; // 刚触碰到屏幕的时的手指信息
    var centerY = 0; // 用来记录每次触摸时上一次的偏移距离
    var maxDown = 50; // 设定一个最大向下滑动的距离
    var maxUp = -(ul.offsetHeight - draw.offsetHeight + maxDown); // 求得一个最大向上滑动的距离
    var maxUpBounce = 0; // 向上反弹值
    var maxDownBounce = -(ul.offsetHeight - draw.offsetHeight); // 向下反弹值

    // touchstart 时,记录手指在 Y 轴上的落点距离可视顶部距离
    ul.addEventListener('touchstart', function (e) {
      startY = e.changedTouches[0].clientY;
    })

    // touchmove 时,记录此时手指在 Y 轴上的落点距离可视顶部距离
    ul.addEventListener('touchmove', function (e) {
      // 清除过渡
      ul.style.transition = 'none';
      // 获取差值
      var dy = e.changedTouches[0].clientY - startY;

      // 上次的滑动距离加上本次的滑动距离
      var tempY = centerY + dy;

      // 当上次滑动的距离加上本次滑动的距离 大于 设定的最大向下距离的时候
      if (tempY > maxDown) {
        tempY = maxDown;
      }
      // 当上次滑动的距离加上本次滑动的距离 小于 设定的最大向上距离的时候 
      else if (tempY < maxUp) {
        tempY = maxUp;
      }

      // 设置 ul 在 Y 轴上的偏移
      ul.style.transform = &#39;translateY(&#39; + tempY + &#39;px)&#39;;
    })

    // touchend 时,记录此时手指在 Y 轴上的落点距离可视顶部距离
    ul.addEventListener(&#39;touchend&#39;, function (e) {
      // 获取差值
      var dy = e.changedTouches[0].clientY - startY;
      // 记录移动的距离
      centerY = centerY + dy;

      // 两次滑动的距离 大于 设定的 向上 反弹值时
      if (centerY > maxUpBounce) {
        // 让两次滑动的距离 等于 设置的值
        centerY = maxUpBounce;
        // 添加过渡
        ul.style.transition = 'transform .5s';
        ul.style.transform = 'translateY(' + centerY + 'px)';
      }
      // 两次滑动的距离 小于 设定的 向下 反弹值时
      else if (centerY < maxDownBounce) {
        // 让两次滑动的距离 等于 设置的值
        centerY = maxDownBounce;
        // 添加过渡
        ul.style.transition = &#39;transform .5s&#39;;
        ul.style.transform = &#39;translateY(&#39; + centerY + &#39;px)&#39;;
      }
    })
  </script>
</body>

</html>
登录后复制

以上是原生js实现移动端Touch滑动反弹的方法(代码示例)的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

vue中怎么用bootstrap vue中怎么用bootstrap Apr 07, 2025 pm 11:33 PM

在 Vue.js 中使用 Bootstrap 分为五个步骤:安装 Bootstrap。在 main.js 中导入 Bootstrap。直接在模板中使用 Bootstrap 组件。可选:自定义样式。可选:使用插件。

HTML,CSS和JavaScript的角色:核心职责 HTML,CSS和JavaScript的角色:核心职责 Apr 08, 2025 pm 07:05 PM

HTML定义网页结构,CSS负责样式和布局,JavaScript赋予动态交互。三者在网页开发中各司其职,共同构建丰富多彩的网站。

了解HTML,CSS和JavaScript:初学者指南 了解HTML,CSS和JavaScript:初学者指南 Apr 12, 2025 am 12:02 AM

WebDevelovermentReliesonHtml,CSS和JavaScript:1)HTMLStructuresContent,2)CSSStyleSIT和3)JavaScriptAddSstractivity,形成thebasisofmodernWebemodernWebExexperiences。

bootstrap怎么设置框架 bootstrap怎么设置框架 Apr 07, 2025 pm 03:27 PM

要设置 Bootstrap 框架,需要按照以下步骤:1. 通过 CDN 引用 Bootstrap 文件;2. 下载文件并将其托管在自己的服务器上;3. 在 HTML 中包含 Bootstrap 文件;4. 根据需要编译 Sass/Less;5. 导入定制文件(可选)。设置完成后,即可使用 Bootstrap 的网格系统、组件和样式创建响应式网站和应用程序。

bootstrap怎么写分割线 bootstrap怎么写分割线 Apr 07, 2025 pm 03:12 PM

创建 Bootstrap 分割线有两种方法:使用 标签,可创建水平分割线。使用 CSS border 属性,可创建自定义样式的分割线。

bootstrap怎么插入图片 bootstrap怎么插入图片 Apr 07, 2025 pm 03:30 PM

在 Bootstrap 中插入图片有以下几种方法:直接插入图片,使用 HTML 的 img 标签。使用 Bootstrap 图像组件,可以提供响应式图片和更多样式。设置图片大小,使用 img-fluid 类可以使图片自适应。设置边框,使用 img-bordered 类。设置圆角,使用 img-rounded 类。设置阴影,使用 shadow 类。调整图片大小和位置,使用 CSS 样式。使用背景图片,使用 background-image CSS 属性。

H5指的是什么?探索上下文 H5指的是什么?探索上下文 Apr 12, 2025 am 12:03 AM

H5referstoHTML5,apivotaltechnologyinwebdevelopment.1)HTML5introducesnewelementsandAPIsforrich,dynamicwebapplications.2)Itsupportsmultimediawithoutplugins,enhancinguserexperienceacrossdevices.3)SemanticelementsimprovecontentstructureandSEO.4)H5'srespo

bootstrap按钮怎么用 bootstrap按钮怎么用 Apr 07, 2025 pm 03:09 PM

如何使用 Bootstrap 按钮?引入 Bootstrap CSS创建按钮元素并添加 Bootstrap 按钮类添加按钮文本

See all articles