web前端|js教程
css,移动web开发,html5,javascript
web前端-js教程
本篇文章给大家带来的内容是关于原生js实现移动端Touch滑动反弹的方法(代码示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。
自动考试 源码,ubuntu. efi分区,tomcat6闪退怎么解决,爬虫 a股市场,asp和php有什么区别,seo多钱lzw
移动端 Touch 滑动反弹
易语言攻击电脑源码,vscode64下载地址,ubuntu简单编程,tomcat可以同时运行,js 网页 爬虫,php导出txt文件,萝岗seo网络营销平台lzw
什么是Touch滑动?就是类似于PC端的滚动事件,但是在移动端是没有滚动事件的,所以就要用到Touch事件结合js去实现,效果如下:
地方信息网站源码,vscode安装C盘,ubuntu文件管理,tomcat主备,sqlite 插件,webstrom网页设计,jsp与数据库联系中的密码是,动态ip服务器是什么,今日头条插件,web前端框架开发技术交流,书目爬虫,solr php,绵阳seo公司,启动springboot包,调用tag标签,网站 防止采集,网页模板国外,oa html模板,zencart后台教程,菜单图标 页面,php选修课程管理系统,易语言应用程序逆向工具lzw
1. 准备工作
什么是移动端的Touch事件?在移动端Touch事件可以细分成三种,分别是:touchstart、touchmove和touchend,并且touch事件必须要用addEventListener去监听。
touchStart当手指触碰到屏幕的时候触发
touchmove当手指在屏幕上不断移动的时候触发
touchend当手指离开屏幕的时候触发
Touch 事件触发的 Event 对象:
// 手指触碰到屏幕时触发element.addEventListener( ouchstart, function (e) { // 打印的事件对象 console.log(e);})
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部分:
列表一列表二列表三列表四列表五列表六列表七列表八列表九列表十
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;}
效果图:
3. 首次滑动
手指触摸到列表向下滑动的时候,列表应该跟着向下滑动,当手指离开屏幕的时候,列表应该停在滑动的位置。这里就会用到上面准备阶段的知识点了,不明白的可以参考上面的概念。
实现原理:
1、touchstart的时候,获取手指触摸的落点A,通过这个点对象里面的clientY属性,获取距离顶部可视区的距离;
2、touchmove的时候,获取手指的点B,同样的获取移动时距离顶部可视区的距离;
3、touchmove的时候,还要做另一件事情,就是获取两点的差值(B.clientY-A.clientY),将这个差值动态赋值给ul,ul只需要设置向Y轴方向偏移这个距离,就能实现列表随手指滑动
先来张示意图,怎么通过 js 让列表滑动起来:
示例代码:
var draw = document.querySelector(#draw);var ul = draw.children[0];// touchstart 时,记录手指在 Y 轴上的落点距离可视顶部距离var startY = 0ul.addEventListener( ouchstart, function (e) { startY = e.changedTouches[0].clientY;})// touchmove 时,记录此时手指在 Y 轴上的落点距离可视顶部距离ul.addEventListener( ouchmove, function (e) { // 获取差值 var dy = e.changedTouches[0].clientY - startY; // 设置 ul 在 Y 轴上的偏移 ul.style.transform = ranslateY( + dy + px);})
效果图:
4. 再次滑动
上面的效果图,细心的朋友可能已经发现了问题,在第一次的时候,得到了我们想要的效果,但是在第二次的时候,我们继续向下移动了一段距离,但是ul并没有接着第一次的位置继续向下,而是瞬间跳了上去。
问题分析:
虽然第二次是继续向下移动了一段距离,但是触摸结束后,最终是将此时的差值,重新赋值给了ul的Y轴偏移,所以视觉上“跳了上去”。
解决方法:
每一次滑动结束之后,都应该记录下此次滑动的距离,与之前的进行累加,待下一次滑动的时候,ul在Y轴的偏移值应该是之前的距离加上本次滑动的距离。
新增touchend事件,在该事件里同样的可以获取到本次滑动的距离,将它与上一次的距离相加,赋值给一个全局变量;
在touchmove事件里有点小改动,就是在给ul设置偏移值的时候,除了本次滑动的差值还要加上这个上一次的值;
示意图:
示例代码:
var draw = document.querySelector(#draw);var ul = draw.children[0];var startY = 0 // 刚触碰到屏幕的时的手指信息var centerY = 0 // 用来记录每次触摸时上一次的偏移距离// touchstart 时,记录手指在 Y 轴上的落点距离可视顶部距离ul.addEventListener( ouchstart, function (e) { startY = e.changedTouches[0].clientY;})// touchmove 时,记录此时手指在 Y 轴上的落点距离可视顶部距离ul.addEventListener( ouchmove, function (e) { // 获取差值 var dy = e.changedTouches[0].clientY - startY; // 上次的滑动距离加上本次的滑动距离 var tempY = centerY + dy; // 设置 ul 在 Y 轴上的偏移 ul.style.transform = ranslateY( + tempY + px);})// touchend 时,记录此时手指在 Y 轴上的落点距离可视顶部距离ul.addEventListener( ouchend, function (e) { // 获取差值 var dy = e.changedTouches[0].clientY - startY; // 记录移动的距离 centerY = centerY + dy;})
效果图:
5. 限制滑动区间
到上面一步,我们已经可以实现列表的滑动了,但是也存在一个问题,就是向上或者向下的时候没有限制,上下可以无限的滑动,甚至再用点力,就看不到列表了。为了美观和实用,这样肯定不行的,需要给它设定一个区间,设定向上或者向下最多只能留白多少。
限制向下滑动最大区间:
示例代码:
var maxDown = 50; // 设定一个最大向下滑动的距离// touchmove 时,记录此时手指在 Y 轴上的落点距离可视顶部距离ul.addEventListener( ouchmove, function (e) { // 获取差值 var dy = e.changedTouches[0].clientY - startY; // 上次的滑动距离加上本次的滑动距离 var tempY = centerY + dy; // 当上次滑动的距离加上本次滑动的距离 大于 设定的最大向下距离的时候 if (tempY > maxDown) { // 直接让偏移的值 等于这个设定值 tempY = maxDown; } // 设置 ul 在 Y 轴上的偏移 ul.style.transform = ranslateY( + tempY + px);})
限制向上滑动最大区间:
求出向上滑动最大值:
注意:因为ul
是向上滑动的,所以求得的距离前面要加上一个负号(-
)
示例代码:
// 设定一个最大向下滑动的距离var maxDown = 50; // 求得一个最大向上滑动的距离var maxUp = -(ul.offsetHeight - draw.offsetHeight + maxDown); // touchmove 时,记录此时手指在 Y 轴上的落点距离可视顶部距离ul.addEventListener( ouchmove, 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 = ranslateY( + tempY + px);})
效果图:
认真观察上图,虽然成功的设置了最大滑动区间,但是你有没有发现,一直往一个方向滑动的时候,虽然列表不会继续往下滑动,但是接着往相反方向滑动的时候,感觉列表滑不动,需要滑一段距离后,列表才会跟着走,这是为什么呢?因为滑动的过程centerY
是一直变的,列表虽然视觉上不动了,但是在touchend
事件的时候,它的centerY
值一直在累加。解决方法请往下看:
6. 设定反弹区间
设定向上反弹值:
示例代码:
// 向上反弹var maxUpBounce = 0;// touchend 时,记录此时手指在 Y 轴上的落点距离可视顶部距离ul.addEventListener( ouchend, function (e) { // 获取差值 var dy = e.changedTouches[0].clientY - startY; // 记录移动的距离 centerY = centerY + dy; // 两次滑动的距离 大于 设定的 向上 反弹值时 if (centerY > maxUpBounce) { // 让两次滑动的距离 等于 设置的值 centerY = maxUpBounce; // 添加过渡 ul.style.transition = ransform .5s; ul.style.transform = ranslateY( + centerY + px); }})
设定向下反弹值:
示例代码:
// 向上反弹值var maxUpBounce = 0; // 向下反弹值var maxDownBounce = -(ul.offsetHeight - draw.offsetHeight);// touchend 时,记录此时手指在 Y 轴上的落点距离可视顶部距离ul.addEventListener( ouchend, function (e) { // 获取差值 var dy = e.changedTouches[0].clientY - startY; // 记录移动的距离 centerY = centerY + dy; // 两次滑动的距离 大于 设定的 向上 反弹值时 if (centerY > maxUpBounce) { // 让两次滑动的距离 等于 设置的值 centerY = maxUpBounce; // 添加过渡 ul.style.transition = ransform .5s; ul.style.transform = ranslateY( + centerY + px); } // 两次滑动的距离 小于 设定的 向下 反弹值时 else if (centerY < maxDownBounce) { // 让两次滑动的距离 等于 设置的值 centerY = maxDownBounce; // 添加过渡 ul.style.transition = ransform .5s; ul.style.transform = ranslateY( + centerY + px); }})
注意: 在touchend
事件的时候,给列表添加了transition
属性才会有反弹的效果,但是,下一次滑动的时候,touchmove
事件的时候,这个属性还存在,所以就会出现滑动的时候有顿挫感,所以在touchmove
事件的时候,一进来就清一下过渡ul.style.transition =
one;
。
完成后效果图:
7. 完整代码
列表一列表二列表三列表四列表五列表六列表七列表八列表九列表十
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( ouchstart, function (e) {startY = e.changedTouches[0].clientY; }) // touchmove 时,记录此时手指在 Y 轴上的落点距离可视顶部距离 ul.addEventListener( ouchmove, function (e) {// 清除过渡ul.style.transition = one;// 获取差值var dy = e.changedTouches[0].clientY - startY;// 上次的滑动距离加上本次的滑动距离var tempY = centerY + dy;// 当上次滑动的距离加上本次滑动的距离 大于 设定的最大向下距离的时候if (tempY > maxDown) { tempY = maxDown;}// 当上次滑动的距离加上本次滑动的距离 小于 设定的最大向上距离的时候 else if (tempY maxUpBounce) { // 让两次滑动的距离 等于 设置的值 centerY = maxUpBounce; // 添加过渡 ul.style.transition = ransform .5s; ul.style.transform = ranslateY( + centerY + px);}// 两次滑动的距离 小于 设定的 向下 反弹值时else if (centerY < maxDownBounce) { // 让两次滑动的距离 等于 设置的值 centerY = maxDownBounce; // 添加过渡 ul.style.transition = ransform .5s; ul.style.transform = ranslateY( + centerY + px);} })